Skip to content

Commit

Permalink
Merge pull request #18 from raffis/next
Browse files Browse the repository at this point in the history
feat: use klog only as logger
  • Loading branch information
raffis authored Nov 30, 2022
2 parents 9c53d71 + 7b676b6 commit a86b6f5
Show file tree
Hide file tree
Showing 6 changed files with 109 additions and 76 deletions.
4 changes: 4 additions & 0 deletions .github/workflows/pr-build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ name: pr-build

on:
pull_request:
types:
- opened
- synchronize
- reopened

jobs:
build:
Expand Down
14 changes: 12 additions & 2 deletions .goreleaser.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ sboms:

dockers:
- image_templates:
- ghcr.io/raffis/{{ .ProjectName }}:{{ .Version }}
- ghcr.io/raffis/{{ .ProjectName }}:{{ .Version }}-amd64
dockerfile: Dockerfile.release
use: buildx
Expand All @@ -49,7 +48,8 @@ dockers:
- --label=org.opencontainers.image.created={{ time "2006-01-02T15:04:05Z07:00" }}
- --label=org.opencontainers.image.revision={{ .FullCommit }}
- --label=org.opencontainers.image.licenses=MIT
- image_templates: ["ghcr.io/raffis/{{ .ProjectName }}:{{ .Version }}-arm64v8"]
- image_templates:
- "ghcr.io/raffis/{{ .ProjectName }}:{{ .Version }}-arm64v8"
goarch: arm64
dockerfile: Dockerfile.release
use: buildx
Expand All @@ -66,6 +66,16 @@ dockers:
- --label=org.opencontainers.image.revision={{ .FullCommit }}
- --label=org.opencontainers.image.licenses=MIT

docker_manifests:
- name_template: ghcr.io/raffis/{{ .ProjectName }}:{{ .Version }}
image_templates:
- ghcr.io/raffis/{{ .ProjectName }}:{{ .Version }}-amd64
- ghcr.io/raffis/{{ .ProjectName }}:{{ .Version }}-arm64v8
- name_template: ghcr.io/raffis/{{ .ProjectName }}:latest
image_templates:
- ghcr.io/raffis/{{ .ProjectName }}:{{ .Version }}-amd64
- ghcr.io/raffis/{{ .ProjectName }}:{{ .Version }}-arm64v8

brews:
- ids:
- cli
Expand Down
21 changes: 0 additions & 21 deletions cmd/log.go

This file was deleted.

61 changes: 29 additions & 32 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ package main

import (
"context"
"flag"
"fmt"
"io"
"os"
"strconv"
"strings"
Expand Down Expand Up @@ -36,7 +38,6 @@ type args struct {
includeAll bool
labelSelector string
nostream bool
verbose bool
version bool
}

Expand All @@ -52,17 +53,14 @@ const (
func main() {
flags := args{}

defaultLogger := stderrLogger{
stderr: os.Stderr,
}
rootCmd, err := parseCliArgs(&flags)
if err != nil {
defaultLogger.Failuref("%v", err)
fmt.Printf("%v", err)
}

err = rootCmd.Execute()
if err != nil {
defaultLogger.Failuref("%v", err)
fmt.Printf("%v", err)
}

os.Exit(toExitCode(rootCmd.Annotations[statusAnnotation]))
Expand Down Expand Up @@ -91,10 +89,7 @@ func parseCliArgs(flags *args) (*cobra.Command, error) {
cmd.Annotations = make(map[string]string)
cmd.Annotations[statusAnnotation] = strconv.Itoa(statusFail)

status, err := run(kubeconfigArgs, stderrLogger{
stderr: os.Stderr,
verbose: flags.verbose,
}, *flags, printFlags)
status, err := run(kubeconfigArgs, *flags, printFlags)
if err != nil {
return err
}
Expand All @@ -107,6 +102,12 @@ func parseCliArgs(flags *args) (*cobra.Command, error) {
apiServer := ""
kubeconfigArgs.APIServer = &apiServer
kubeconfigArgs.AddFlags(rootCmd.PersistentFlags())

rest.SetDefaultWarningHandler(rest.NewWarningWriter(io.Discard, rest.WarningWriterOptions{}))
set := &flag.FlagSet{}
klog.InitFlags(set)
rootCmd.PersistentFlags().AddGoFlagSet(set)

err := rootCmd.RegisterFlagCompletionFunc("context", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return contextsCompletionFunc(kubeconfigArgs, toComplete)
})
Expand All @@ -115,7 +116,6 @@ func parseCliArgs(flags *args) (*cobra.Command, error) {
}

rootCmd.Flags().StringVarP(printFlags.OutputFormat, "output", "o", *printFlags.OutputFormat, fmt.Sprintf(`Output format. One of: (%s). See custom columns [https://kubernetes.io/docs/reference/kubectl/overview/#custom-columns], golang template [http://golang.org/pkg/text/template/#pkg-overview] and jsonpath template [https://kubernetes.io/docs/reference/kubectl/jsonpath/].`, strings.Join(printFlags.AllowedFormats(), ", ")))
rootCmd.Flags().BoolVarP(&flags.verbose, "verbose", "v", flags.verbose, "Verbose mode (Logged to stderr)")
rootCmd.Flags().BoolVarP(&flags.version, "version", "", flags.version, "Print version and exit")
rootCmd.Flags().BoolVarP(&flags.includeAll, "include-all", "a", flags.includeAll, "Includes resources which are considered dynamic resources")
rootCmd.Flags().StringVarP(&flags.labelSelector, "selector", "l", flags.labelSelector, "Label selector (Is used for all apis)")
Expand All @@ -127,16 +127,12 @@ func parseCliArgs(flags *args) (*cobra.Command, error) {
return rootCmd, nil
}

func run(kubeconfigArgs *genericclioptions.ConfigFlags, logger stderrLogger, flags args, printFlags *k8sget.PrintFlags) (int, error) {
func run(kubeconfigArgs *genericclioptions.ConfigFlags, flags args, printFlags *k8sget.PrintFlags) (int, error) {
if flags.version {
fmt.Printf(`{"version":"%s","sha":"%s","date":"%s"}`+"\n", version, commit, date)
return statusOK, nil
}

if !flags.verbose {
klog.LogToStderr(false)
}

// default processing
gitopsDynClient, err := getDynClient(kubeconfigArgs)
if err != nil {
Expand All @@ -158,7 +154,7 @@ func run(kubeconfigArgs *genericclioptions.ConfigFlags, logger stderrLogger, fla
return statusFail, err
}

resourceCount, zombies, err := detectZombies(logger, flags, printFlags, gitopsDynClient, clusterDynClient, clusterDiscoveryClient, gitopsRestClient, *kubeconfigArgs.Namespace)
resourceCount, zombies, err := detectZombies(flags, printFlags, gitopsDynClient, clusterDynClient, clusterDiscoveryClient, gitopsRestClient, *kubeconfigArgs.Namespace)
if err != nil {
return statusFail, err
}
Expand All @@ -181,38 +177,38 @@ func run(kubeconfigArgs *genericclioptions.ConfigFlags, logger stderrLogger, fla
return statusOK, nil
}

func detectZombies(logger stderrLogger, flags args, printFlags *k8sget.PrintFlags, gitopsDynClient, clusterDynClient dynamic.Interface, clusterDiscoveryClient *discovery.DiscoveryClient, gitopsRestClient *rest.RESTClient, namespace string) (int, []unstructured.Unstructured, error) {
func detectZombies(flags args, printFlags *k8sget.PrintFlags, gitopsDynClient, clusterDynClient dynamic.Interface, clusterDiscoveryClient *discovery.DiscoveryClient, gitopsRestClient *rest.RESTClient, namespace string) (int, []unstructured.Unstructured, error) {
var (
resourceCount int
zombies []unstructured.Unstructured
)

helmReleases, kustomizations, err := listGitopsResources(logger, flags, gitopsDynClient, gitopsRestClient)
helmReleases, kustomizations, err := listGitopsResources(flags, gitopsDynClient, gitopsRestClient)
if err != nil {
return 0, nil, err
}

logger.Debugf("discover all api groups and resources")
klog.V(1).Infof("discover all api groups and resources")
list, err := listServerGroupsAndResources(clusterDiscoveryClient)
if err != nil {
return 0, nil, err
}
for _, g := range list {
logger.Debugf("found group %v with the following resources: ", g.GroupVersion)
klog.V(1).Infof("found group %v with the following resources", g.GroupVersion)
for _, r := range g.APIResources {
var namespaceStr string
if r.Namespaced {
namespaceStr = " (namespaced)"
}
logger.Debugf(" |_ %v%v verbs: %v", r.Kind, namespaceStr, r.Verbs)
klog.V(1).Infof(" |_ %v%v verbs: %v", r.Kind, namespaceStr, r.Verbs)
}
}

ch := make(chan unstructured.Unstructured)
var wgProducer, wgConsumer sync.WaitGroup

discover := collector.NewDiscovery(
logger,
klog.NewKlogr(),
collector.IgnoreOwnedResource(),
collector.IgnoreServiceAccountSecret(),
collector.IgnoreHelmSecret(),
Expand All @@ -221,18 +217,18 @@ func detectZombies(logger stderrLogger, flags args, printFlags *k8sget.PrintFlag
)

for _, group := range list {
logger.Debugf("discover resource group %#v", group.GroupVersion)
klog.V(1).Infof("discover resource group %#v", group.GroupVersion)
gv, err := schema.ParseGroupVersion(group.GroupVersion)
if err != nil {
return 0, nil, err
}

for _, resource := range group.APIResources {
logger.Debugf("discover resource %#v.%#v.%#v", resource.Name, resource.Group, resource.Version)
klog.V(1).Infof("discover resource %#v.%#v.%#v", resource.Name, resource.Group, resource.Version)

gvr, err := validateResource(namespace, gv, resource, flags)
if err != nil {
logger.Debugf(err.Error())
klog.V(1).Infof(err.Error())
continue
}

Expand All @@ -245,7 +241,7 @@ func detectZombies(logger stderrLogger, flags args, printFlags *k8sget.PrintFlag

count, err := handleResource(context.TODO(), discover, resAPI, ch, flags)
if err != nil {
logger.Failuref("could not handle resource: %s", err)
klog.Errorf("could not handle resource: %w", err)
}
resourceCount += count
}(resAPI)
Expand All @@ -271,23 +267,24 @@ func detectZombies(logger stderrLogger, flags args, printFlags *k8sget.PrintFlag
return resourceCount, zombies, nil
}

func listGitopsResources(logger stderrLogger, flags args, gitopsDynClient dynamic.Interface, gitopsRestClient *rest.RESTClient) ([]unstructured.Unstructured, []ksapi.Kustomization, error) {
logger.Debugf("discover all helmreleases")
func listGitopsResources(flags args, gitopsDynClient dynamic.Interface, gitopsRestClient *rest.RESTClient) ([]unstructured.Unstructured, []ksapi.Kustomization, error) {
klog.V(1).Infof("discover all helmreleases")
helmReleases, err := listHelmReleases(context.TODO(), gitopsDynClient, flags)
if err != nil {
return nil, nil, fmt.Errorf("failed to get helmreleases: %w", err)
}
for _, h := range helmReleases {
logger.Debugf(h.GetName())
klog.V(1).Infof(" |_ %s.%s", h.GetName(), h.GetNamespace())
}

logger.Debugf("discover all kustomizations")
klog.V(1).Infof("discover all kustomizations")
kustomizations, err := listKustomizations(context.TODO(), gitopsRestClient)
if err != nil {
return nil, nil, fmt.Errorf("failed to get kustomizations: %w", err)
}

for _, k := range kustomizations {
logger.Debugf(k.GetName())
klog.V(1).Infof(" |_ %s.%s", k.GetName(), k.GetNamespace())
}

return helmReleases, kustomizations, nil
Expand Down
34 changes: 16 additions & 18 deletions pkg/collector/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (

ksapi "github.com/fluxcd/kustomize-controller/api/v1beta2"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/klog/v2"
)

const (
Expand All @@ -16,24 +17,20 @@ const (
)

// FilterFunc is a function that filters resources.
type FilterFunc func(res unstructured.Unstructured, logger logger) bool
type FilterFunc func(res unstructured.Unstructured, logger klog.Logger) bool

// Interface represents collector interface.
type Interface interface {
Discover(ctx context.Context, list *unstructured.UnstructuredList, ch chan unstructured.Unstructured) error
}

type logger interface {
Debugf(format string, a ...interface{})
}

type discovery struct {
filters []FilterFunc
logger logger
logger klog.Logger
}

// NewDiscovery returns a new discovery instance.
func NewDiscovery(logger logger, filters ...FilterFunc) Interface {
func NewDiscovery(logger klog.Logger, filters ...FilterFunc) Interface {
return &discovery{
logger: logger,
filters: filters,
Expand All @@ -44,7 +41,7 @@ func NewDiscovery(logger logger, filters ...FilterFunc) Interface {
func (d *discovery) Discover(ctx context.Context, list *unstructured.UnstructuredList, ch chan unstructured.Unstructured) error {
RESOURCES:
for _, res := range list.Items {
d.logger.Debugf("validate resource %s %s %s", res.GetName(), res.GetNamespace(), res.GetAPIVersion())
d.logger.V(1).Info("validate resource", "name", res.GetName(), "namespace", res.GetNamespace(), "apiVersion", res.GetAPIVersion())

for _, filter := range d.filters {
if filter(res, d.logger) {
Expand All @@ -60,9 +57,9 @@ RESOURCES:

// IgnoreOwnedResource returns a FilterFunc which filters resources owner by parents ones.
func IgnoreOwnedResource() FilterFunc {
return func(res unstructured.Unstructured, logger logger) bool {
return func(res unstructured.Unstructured, logger klog.Logger) bool {
if refs := res.GetOwnerReferences(); len(refs) > 0 {
logger.Debugf("ignore resource owned by parent %s %s %s", res.GetName(), res.GetNamespace(), res.GetAPIVersion())
klog.V(1).Info("ignore resource owned by parent", "name", res.GetName(), "namespace", res.GetNamespace(), "apiVersion", res.GetAPIVersion())
return true
}

Expand All @@ -72,7 +69,7 @@ func IgnoreOwnedResource() FilterFunc {

// IgnoreServiceAccountSecret returns a FilterFunc which filters secrets linked to a service account.
func IgnoreServiceAccountSecret() FilterFunc {
return func(res unstructured.Unstructured, logger logger) bool {
return func(res unstructured.Unstructured, logger klog.Logger) bool {
if res.GetKind() == "Secret" && res.GetAPIVersion() == "v1" {
if _, ok := res.GetAnnotations()["kubernetes.io/service-account.name"]; ok {
return true
Expand All @@ -85,7 +82,7 @@ func IgnoreServiceAccountSecret() FilterFunc {

// IgnoreHelmSecret returns a FilterFunc which filters secrets owned by helm.
func IgnoreHelmSecret() FilterFunc {
return func(res unstructured.Unstructured, logger logger) bool {
return func(res unstructured.Unstructured, logger klog.Logger) bool {
if res.GetKind() == "Secret" && res.GetAPIVersion() == "v1" {
if v, ok := res.GetLabels()["owner"]; ok && v == "helm" {
return true
Expand All @@ -98,14 +95,15 @@ func IgnoreHelmSecret() FilterFunc {

// IgnoreIfHelmReleaseFound returns a FilterFunc which filters resources part of an helm release.
func IgnoreIfHelmReleaseFound(helmReleases []unstructured.Unstructured) FilterFunc {
return func(res unstructured.Unstructured, logger logger) bool {
return func(res unstructured.Unstructured, logger klog.Logger) bool {
labels := res.GetLabels()
if helmName, ok := labels[fluxHelmNameLabel]; ok {
if helmNamespace, ok := labels[fluxHelmNamespaceLabel]; ok {
if hasResource(helmReleases, helmName, helmNamespace) {
return true
}
logger.Debugf("helmrelease [%s.%s] not found from resource %s %s %s\n", helmName, helmNamespace, res.GetName(), res.GetNamespace(), res.GetAPIVersion())

klog.V(1).Info("helmrelease not found from resource", "helmReleaseName", helmName, "helmReleaseNamespace", helmNamespace, "name", res.GetName(), "namespace", res.GetNamespace(), "apiVersion", res.GetAPIVersion())
}
}

Expand All @@ -115,7 +113,7 @@ func IgnoreIfHelmReleaseFound(helmReleases []unstructured.Unstructured) FilterFu

// IgnoreIfKustomizationFound returns a FilterFunc which filters resources part of a flux kustomization.
func IgnoreIfKustomizationFound(kustomizations []ksapi.Kustomization) FilterFunc {
return func(res unstructured.Unstructured, logger logger) bool {
return func(res unstructured.Unstructured, logger klog.Logger) bool {
labels := res.GetLabels()
ksName, okKsName := labels[fluxKustomizeNameLabel]
ksNamespace, okKsNamespace := labels[fluxKustomizeNamespaceLabel]
Expand All @@ -125,7 +123,7 @@ func IgnoreIfKustomizationFound(kustomizations []ksapi.Kustomization) FilterFunc

if ks := findKustomization(kustomizations, ksName, ksNamespace); ks != nil {
id := fmt.Sprintf("%s_%s_%s_%s", res.GetNamespace(), res.GetName(), res.GroupVersionKind().Group, res.GroupVersionKind().Kind)
logger.Debugf("lookup kustomization [%s.%s] inventory for %s", ksName, ksNamespace, id)
klog.V(1).Info("lookup kustomization inventory", "kustomizationName", ksName, "kustomizationNamespace", ksNamespace, "resourceId", id)

if ks.Status.Inventory != nil {
for _, entry := range ks.Status.Inventory.Entries {
Expand All @@ -135,10 +133,10 @@ func IgnoreIfKustomizationFound(kustomizations []ksapi.Kustomization) FilterFunc
}
}

logger.Debugf("resource %s %s %s is not part of the kustomization [%s.%s] inventory", res.GetName(), res.GetNamespace(), res.GetAPIVersion(), ksName, ksNamespace)
klog.V(1).Info("resource is not part of the kustomization inventory", "name", res.GetName(), "namespace", res.GetNamespace(), "apiVersion", res.GetAPIVersion(), "kustomizationName", ksName, "kustomizationNamespace", ksNamespace)
return false
}
logger.Debugf("kustomization [%s.%s] not found from resource %s %s %s\n", ksName, ksNamespace, res.GetName(), res.GetNamespace(), res.GetAPIVersion())
klog.V(1).Info("kustomization not found from resource", res.GetName(), "namespace", res.GetNamespace(), "apiVersion", res.GetAPIVersion(), "kustomizationName", ksName, "kustomizationNamespace", ksNamespace)
return false
}
}
Expand Down
Loading

0 comments on commit a86b6f5

Please sign in to comment.