Skip to content

Commit

Permalink
feat: Support --include-types flag to only include resource types in …
Browse files Browse the repository at this point in the history
…relationship discovery

Refs: #3
Signed-off-by: Justin Toh <tohjustin@hotmail.com>
  • Loading branch information
tohjustin committed Mar 4, 2022
1 parent 8619c0a commit ef94175
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 24 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ Flags for configuring relationship discovery parameters
| `--dependencies`, `-D` | If present, list object dependencies instead of dependents. <br/> Not supported in `helm` subcommand |
| `--depth`, `-d` | Maximum depth to find relationships |
| `--exclude-types` | Accepts a comma separated list of resource types to exclude from relationship discovery. <br/> You can also use multiple flag options like --exclude-types type1 --exclude-types type2... |
| `--include-types` | Accepts a comma separated list of resource types to only include in relationship discovery. <br/> You can also use multiple flag options like --include-types type1 --include-types type2... |
| `--scopes`, `-S` | Accepts a comma separated list of additional namespaces to find relationships. <br/> You can also use multiple flag options like -S namespace1 -S namespace2... |

Flags for configuring output format
Expand Down
22 changes: 14 additions & 8 deletions internal/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -218,16 +218,22 @@ func decodeIntoTable(obj runtime.Object) (*metav1.Table, error) {
//nolint:funlen,gocognit
func (c *client) List(ctx context.Context, opts ListOptions) (*unstructuredv1.UnstructuredList, error) {
klog.V(4).Infof("List with options: %+v", opts)
var err error
apis := opts.APIResourcesToInclude
if len(apis) == 0 {
apis, err = c.GetAPIResources(ctx)
if err != nil {
return nil, err
}
apis, err := c.GetAPIResources(ctx)
if err != nil {
return nil, err
}

// Exclude resources
// Filter APIs
if len(opts.APIResourcesToInclude) > 0 {
includeGKSet := ResourcesToGroupKindSet(opts.APIResourcesToInclude)
newAPIs := []APIResource{}
for _, api := range apis {
if _, ok := includeGKSet[api.GroupKind()]; ok {
newAPIs = append(newAPIs, api)
}
}
apis = newAPIs
}
if len(opts.APIResourcesToExclude) > 0 {
excludeGKSet := ResourcesToGroupKindSet(opts.APIResourcesToExclude)
newAPIs := []APIResource{}
Expand Down
18 changes: 13 additions & 5 deletions pkg/cmd/helm/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@ import (
const (
flagAllNamespaces = "all-namespaces"
flagAllNamespacesShorthand = "A"
flagExcludeTypes = "exclude-types"
flagDepth = "depth"
flagDepthShorthand = "d"
flagExcludeTypes = "exclude-types"
flagIncludeTypes = "include-types"
flagScopes = "scopes"
flagScopesShorthand = "S"
)
Expand All @@ -25,6 +26,7 @@ type Flags struct {
AllNamespaces *bool
Depth *uint
ExcludeTypes *[]string
IncludeTypes *[]string
Scopes *[]string
}

Expand All @@ -44,12 +46,16 @@ func (f *Flags) AddFlags(flags *pflag.FlagSet) {
flags.UintVarP(f.Depth, flagDepth, flagDepthShorthand, *f.Depth, "Maximum depth to find relationships")
}
if f.ExcludeTypes != nil {
excludeTypesUsage := fmt.Sprintf("Accepts a comma separated list of resource types to exclude from relationship discovery. You can also use multiple flag options like --%s resource1 --%s resource2...", flagExcludeTypes, flagExcludeTypes)
flags.StringSliceVar(f.ExcludeTypes, flagExcludeTypes, *f.ExcludeTypes, excludeTypesUsage)
usage := fmt.Sprintf("Accepts a comma separated list of resource types to exclude from relationship discovery. You can also use multiple flag options like --%s kind1 --%s kind1...", flagExcludeTypes, flagExcludeTypes)
flags.StringSliceVar(f.ExcludeTypes, flagExcludeTypes, *f.ExcludeTypes, usage)
}
if f.IncludeTypes != nil {
usage := fmt.Sprintf("Accepts a comma separated list of resource types to only include in relationship discovery. You can also use multiple flag options like --%s kind1 --%s kind1...", flagIncludeTypes, flagIncludeTypes)
flags.StringSliceVar(f.IncludeTypes, flagIncludeTypes, *f.IncludeTypes, usage)
}
if f.Scopes != nil {
scopesUsage := fmt.Sprintf("Accepts a comma separated list of additional namespaces to find relationships. You can also use multiple flag options like -%s namespace1 -%s namespace2...", flagScopesShorthand, flagScopesShorthand)
flags.StringSliceVarP(f.Scopes, flagScopes, flagScopesShorthand, *f.Scopes, scopesUsage)
usage := fmt.Sprintf("Accepts a comma separated list of additional namespaces to find relationships. You can also use multiple flag options like -%s namespace1 -%s namespace2...", flagScopesShorthand, flagScopesShorthand)
flags.StringSliceVarP(f.Scopes, flagScopes, flagScopesShorthand, *f.Scopes, usage)
}
}

Expand All @@ -69,12 +75,14 @@ func NewFlags() *Flags {
allNamespaces := false
depth := uint(0)
excludeTypes := []string{}
includeTypes := []string{}
scopes := []string{}

return &Flags{
AllNamespaces: &allNamespaces,
Depth: &depth,
ExcludeTypes: &excludeTypes,
IncludeTypes: &includeTypes,
Scopes: &scopes,
}
}
38 changes: 34 additions & 4 deletions pkg/cmd/helm/helm.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ func (o *CmdOptions) Validate() error {
klog.V(4).Infof("Flags.AllNamespaces: %t", *o.Flags.AllNamespaces)
klog.V(4).Infof("Flags.Depth: %v", *o.Flags.Depth)
klog.V(4).Infof("Flags.ExcludeTypes: %v", *o.Flags.ExcludeTypes)
klog.V(4).Infof("Flags.IncludeTypes: %v", *o.Flags.IncludeTypes)
klog.V(4).Infof("Flags.Scopes: %v", *o.Flags.Scopes)
klog.V(4).Infof("ClientFlags.Context: %s", *o.ClientFlags.Context)
klog.V(4).Infof("ClientFlags.Namespace: %s", *o.ClientFlags.Namespace)
Expand All @@ -186,7 +187,7 @@ func (o *CmdOptions) Validate() error {
}

// Run implements all the necessary functionality for the helm command.
//nolint:funlen,gocognit
//nolint:funlen,gocognit,gocyclo
func (o *CmdOptions) Run() error {
ctx := context.Background()

Expand Down Expand Up @@ -228,8 +229,34 @@ func (o *CmdOptions) Run() error {
excludeAPIs = append(excludeAPIs, *api)
}
}
includeAPIs := []client.APIResource{}
if o.Flags.IncludeTypes != nil {
for _, kind := range *o.Flags.IncludeTypes {
api, err := o.Client.ResolveAPIResource(kind)
if err != nil {
return err
}
includeAPIs = append(includeAPIs, *api)
}
}

// Filter out objects that matches any excluded resource
// Keep only objects that matches any included resource type
if len(includeAPIs) > 0 {
includeGKSet := client.ResourcesToGroupKindSet(includeAPIs)
newRlsObjs := []unstructuredv1.Unstructured{}
for _, i := range rlsObjs {
if _, ok := includeGKSet[i.GroupVersionKind().GroupKind()]; ok {
newRlsObjs = append(newRlsObjs, i)
}
}
rlsObjs = newRlsObjs
if stgObj != nil {
if _, ok := includeGKSet[stgObj.GroupVersionKind().GroupKind()]; !ok {
stgObj = nil
}
}
}
// Filter out objects that matches any excluded resource type
if len(excludeAPIs) > 0 {
excludeGKSet := client.ResourcesToGroupKindSet(excludeAPIs)
newRlsObjs := []unstructuredv1.Unstructured{}
Expand All @@ -239,8 +266,10 @@ func (o *CmdOptions) Run() error {
}
}
rlsObjs = newRlsObjs
if _, ok := excludeGKSet[stgObj.GroupVersionKind().GroupKind()]; ok {
stgObj = nil
if stgObj != nil {
if _, ok := excludeGKSet[stgObj.GroupVersionKind().GroupKind()]; ok {
stgObj = nil
}
}
}

Expand All @@ -263,6 +292,7 @@ func (o *CmdOptions) Run() error {
// Fetch resources in the cluster
objs, err := o.Client.List(ctx, client.ListOptions{
APIResourcesToExclude: excludeAPIs,
APIResourcesToInclude: includeAPIs,
Namespaces: namespaces,
})
if err != nil {
Expand Down
22 changes: 15 additions & 7 deletions pkg/cmd/lineage/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,14 @@ import (
const (
flagAllNamespaces = "all-namespaces"
flagAllNamespacesShorthand = "A"
flagExcludeTypes = "exclude-types"
flagDependencies = "dependencies"
flagDependenciesShorthand = "D"
flagDepth = "depth"
flagDepthShorthand = "d"
flagExcludeTypes = "exclude-types"
flagIncludeTypes = "include-types"
flagScopes = "scopes"
flagScopesShorthand = "S"
flagDependencies = "dependencies"
flagDependenciesShorthand = "D"
)

// Flags composes common configuration flag structs used in the command.
Expand All @@ -28,6 +29,7 @@ type Flags struct {
Dependencies *bool
Depth *uint
ExcludeTypes *[]string
IncludeTypes *[]string
Scopes *[]string
}

Expand All @@ -50,12 +52,16 @@ func (f *Flags) AddFlags(flags *pflag.FlagSet) {
flags.UintVarP(f.Depth, flagDepth, flagDepthShorthand, *f.Depth, "Maximum depth to find relationships")
}
if f.ExcludeTypes != nil {
excludeTypesUsage := fmt.Sprintf("Accepts a comma separated list of resource types to exclude from relationship discovery. You can also use multiple flag options like --%s kind1 --%s kind1...", flagExcludeTypes, flagExcludeTypes)
flags.StringSliceVar(f.ExcludeTypes, flagExcludeTypes, *f.ExcludeTypes, excludeTypesUsage)
usage := fmt.Sprintf("Accepts a comma separated list of resource types to exclude from relationship discovery. You can also use multiple flag options like --%s kind1 --%s kind1...", flagExcludeTypes, flagExcludeTypes)
flags.StringSliceVar(f.ExcludeTypes, flagExcludeTypes, *f.ExcludeTypes, usage)
}
if f.IncludeTypes != nil {
usage := fmt.Sprintf("Accepts a comma separated list of resource types to only include in relationship discovery. You can also use multiple flag options like --%s kind1 --%s kind1...", flagIncludeTypes, flagIncludeTypes)
flags.StringSliceVar(f.IncludeTypes, flagIncludeTypes, *f.IncludeTypes, usage)
}
if f.Scopes != nil {
scopesUsage := fmt.Sprintf("Accepts a comma separated list of additional namespaces to find relationships. You can also use multiple flag options like -%s namespace1 -%s namespace2...", flagScopesShorthand, flagScopesShorthand)
flags.StringSliceVarP(f.Scopes, flagScopes, flagScopesShorthand, *f.Scopes, scopesUsage)
usage := fmt.Sprintf("Accepts a comma separated list of additional namespaces to find relationships. You can also use multiple flag options like -%s namespace1 -%s namespace2...", flagScopesShorthand, flagScopesShorthand)
flags.StringSliceVarP(f.Scopes, flagScopes, flagScopesShorthand, *f.Scopes, usage)
}
}

Expand All @@ -76,13 +82,15 @@ func NewFlags() *Flags {
dependencies := false
depth := uint(0)
excludeTypes := []string{}
includeTypes := []string{}
scopes := []string{}

return &Flags{
AllNamespaces: &allNamespaces,
Dependencies: &dependencies,
Depth: &depth,
ExcludeTypes: &excludeTypes,
IncludeTypes: &includeTypes,
Scopes: &scopes,
}
}
12 changes: 12 additions & 0 deletions pkg/cmd/lineage/lineage.go
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ func (o *CmdOptions) Validate() error {
klog.V(4).Infof("Flags.Dependencies: %t", *o.Flags.Dependencies)
klog.V(4).Infof("Flags.Depth: %v", *o.Flags.Depth)
klog.V(4).Infof("Flags.ExcludeTypes: %v", *o.Flags.ExcludeTypes)
klog.V(4).Infof("Flags.IncludeTypes: %v", *o.Flags.IncludeTypes)
klog.V(4).Infof("Flags.Scopes: %v", *o.Flags.Scopes)
klog.V(4).Infof("ClientFlags.Context: %s", *o.ClientFlags.Context)
klog.V(4).Infof("ClientFlags.Namespace: %s", *o.ClientFlags.Namespace)
Expand Down Expand Up @@ -227,6 +228,16 @@ func (o *CmdOptions) Run() error {
excludeAPIs = append(excludeAPIs, *api)
}
}
includeAPIs := []client.APIResource{}
if o.Flags.IncludeTypes != nil {
for _, kind := range *o.Flags.IncludeTypes {
api, err := o.Client.ResolveAPIResource(kind)
if err != nil {
return err
}
includeAPIs = append(includeAPIs, *api)
}
}

// Determine the namespaces to list objects
namespaces := []string{o.Namespace}
Expand All @@ -240,6 +251,7 @@ func (o *CmdOptions) Run() error {
// Fetch resources in the cluster
objs, err := o.Client.List(ctx, client.ListOptions{
APIResourcesToExclude: excludeAPIs,
APIResourcesToInclude: includeAPIs,
Namespaces: namespaces,
})
if err != nil {
Expand Down

0 comments on commit ef94175

Please sign in to comment.