Skip to content

Commit

Permalink
Using Cobra for defining CLI commands and flags (#282)
Browse files Browse the repository at this point in the history
* Using Cobra for defining CLI commands and flags

Also, making Provider a proper type

Signed-off-by: Ziv Nevo <nevo@il.ibm.com>
  • Loading branch information
zivnevo authored Jun 26, 2024
1 parent fd1a702 commit 7946a88
Show file tree
Hide file tree
Showing 13 changed files with 191 additions and 128 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
REPOSITORY := github.com/np-guard/cloud-resource-collector
EXE:=collect
EXE:=collector

mod: go.mod
@echo -- $@ --
Expand Down
35 changes: 17 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,31 +46,30 @@ export IBMCLOUD_API_KEY=<ibm-cloud-api-key>

## Usage

### Collecting resources
```
$ ./bin/collect -h
Usage of ./bin/collect:
-get-regions
just print the list of regions for the selected provider
-out string
file path to store results
-provider string
cloud provider from which to collect resources
-region value
cloud region from which to collect resources
-resource-group string
resource group id or name from which to collect resources
./bin/collector collect --provider <provider> [flags]
Flags:
-h, --help help for collect
--out string file path to store results
-r, --region stringArray cloud region from which to collect resources
--resource-group string resource group id or name from which to collect resources
```
* Value of `-provider` must be either `ibm` or `aws`
* The `-region` argument can appear multiple times. If running with no `-region` arguments, resources from all regions are collected.
* If running with no `-resource-group` argument, resources from all resource groups are collected.

## Build the project
* Value of `--provider` must be either `ibm` or `aws`
* **IBM only**: The `--region` argument can appear multiple times. If running with no `--region` arguments, resources from all regions are collected.
* If running with no `--resource-group` argument, resources from all resource groups are collected.

### Listing available regions
```
./bin/collector get-regions --provider <provider>
```

## Build the project
Requires Go version 1.22 or later.
```shell
git clone git@github.com:np-guard/cloud-resource-collector.git
cd cloud-resource-collector
make mod
make build
```

40 changes: 40 additions & 0 deletions cmd/collect/collect_resources.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
Copyright 2023- IBM Inc. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/

package main

import (
"fmt"

"github.com/spf13/cobra"

"github.com/np-guard/cloud-resource-collector/pkg/common"
"github.com/np-guard/cloud-resource-collector/pkg/factory"
)

func collectResources(cmd *cobra.Command, _ []string) error {
cmd.SilenceUsage = true // if we got this far, flags are syntactically correct, so no need to print usage

if provider != common.IBM {
if len(regions) > 0 {
return fmt.Errorf("setting regions from the command-line for provider %s is not yet supported. "+
"Use environment variables or config files instead", provider)
}
if resourceGroupID != "" {
return fmt.Errorf("setting resource-group from the command-line for provider %s is not yet supported. ", provider)
}
}

resources := factory.GetResourceContainer(provider, regions, resourceGroupID)
// Collect resources from the provider API and generate output
err := resources.CollectResourcesFromAPI()
if err != nil {
return err
}
OutputResources(resources, outputFile)
resources.PrintStats()
return nil
}
35 changes: 3 additions & 32 deletions cmd/collect/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,41 +7,12 @@ SPDX-License-Identifier: Apache-2.0
package main

import (
"fmt"
"log"
"strings"

"github.com/np-guard/cloud-resource-collector/pkg/factory"
"github.com/np-guard/cloud-resource-collector/pkg/version"
"os"
)

func main() {
var inArgs InArgs
err := ParseInArgs(&inArgs)
if err != nil {
log.Fatalf("error parsing arguments: %v. exiting...\n", err)
}

if *inArgs.version {
fmt.Printf("cloud-resource-collector v%s\n", version.VersionCore)
return
}

// Initialize a collector for the requested provider
resources := factory.GetResourceContainer(*inArgs.CollectFromProvider, inArgs.regions, *inArgs.resourceGroupID)

if *inArgs.getRegions {
providerRegions := strings.Join(resources.AllRegions(), ", ")
fmt.Printf("Available regions for provider %s: %s\n", *inArgs.CollectFromProvider, providerRegions)
return
}

// Collect resources from the provider API and generate output
err = resources.CollectResourcesFromAPI()
err := newRootCommand().Execute()
if err != nil {
log.Fatal(err)
os.Exit(1) // error was already printed by Cobra
}
OutputResources(resources, *inArgs.OutputFile)

resources.PrintStats()
}
69 changes: 0 additions & 69 deletions cmd/collect/parse_args.go

This file was deleted.

82 changes: 82 additions & 0 deletions cmd/collect/subcmds.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
Copyright 2023- IBM Inc. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/

package main

import (
"fmt"
"strings"

"github.com/spf13/cobra"

"github.com/np-guard/cloud-resource-collector/pkg/common"
"github.com/np-guard/cloud-resource-collector/pkg/factory"
"github.com/np-guard/cloud-resource-collector/pkg/version"
)

const (
providerFlag = "provider"
)

var (
provider common.Provider
regions []string
resourceGroupID string
outputFile string
)

func newRootCommand() *cobra.Command {
rootCmd := &cobra.Command{
Use: "collector",
Short: "cloud-resource-collector is a CLI for collecting VPC-related cloud resources",
Long: `cloud-resource-collector uses cloud-provider SDK to gather VPC-related resources defining network connectivity`,
Version: version.VersionCore,
}

rootCmd.PersistentFlags().VarP(&provider, providerFlag, "p", "collect resources from an account in this cloud provider")
_ = rootCmd.MarkPersistentFlagRequired(providerFlag)

rootCmd.AddCommand(newCollectCommand())
rootCmd.AddCommand(newGetRegionsCommand())

rootCmd.SetHelpCommand(&cobra.Command{Hidden: true}) // disable help command. should use --help flag instead

return rootCmd
}

func newCollectCommand() *cobra.Command {
collectCmd := &cobra.Command{
Use: "collect",
Short: "Collect VPC-related cloud resources",
Long: `Use cloud-provider SDK to gather VPC-related resources defining network connectivity`,
Args: cobra.NoArgs,
RunE: collectResources,
}

collectCmd.Flags().StringArrayVarP(&regions, "region", "r", nil, "cloud region from which to collect resources")
collectCmd.Flags().StringVar(&resourceGroupID, "resource-group", "", "resource group id or name from which to collect resources")
collectCmd.Flags().StringVar(&outputFile, "out", "", "file path to store results")

return collectCmd
}

func newGetRegionsCommand() *cobra.Command {
return &cobra.Command{
Use: "get-regions",
Short: "List available regions for a given provider",
Long: `List all regions that can be used with the --region flag`,
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, _ []string) error {
if provider != common.IBM {
return fmt.Errorf("command not supported for provider %s", provider)
}
resources := factory.GetResourceContainer(provider, nil, "")
providerRegions := strings.Join(resources.AllRegions(), ", ")
fmt.Printf("Available regions for provider %s: %s\n", provider, providerRegions)
return nil
},
}
}
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ require (
github.com/IBM/vpc-go-sdk v0.52.0
github.com/aws/aws-sdk-go-v2/config v1.27.21
github.com/aws/aws-sdk-go-v2/service/ec2 v1.163.0
github.com/spf13/cobra v0.0.3
)

require (
Expand All @@ -35,10 +36,12 @@ require (
github.com/google/uuid v1.6.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-retryablehttp v0.7.7 // indirect
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/leodido/go-urn v1.4.0 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/oklog/ulid v1.3.1 // indirect
github.com/spf13/pflag v1.0.3 // indirect
go.mongodb.org/mongo-driver v1.15.0 // indirect
golang.org/x/crypto v0.24.0 // indirect
golang.org/x/net v0.26.0 // indirect
Expand Down
3 changes: 3 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ github.com/hashicorp/go-retryablehttp v0.6.6/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER
github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU=
github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
Expand Down Expand Up @@ -190,7 +191,9 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR
github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/spf13/cobra v0.0.3 h1:ZlrZ4XsMRm04Fr5pSFxBgfND2EBVa1nLpiy1stUsX/8=
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
Expand Down
2 changes: 1 addition & 1 deletion pkg/aws/resources_container.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ func NewResourcesContainer() *ResourcesContainer {
SecurityGroupsList: []*aws2.SecurityGroup{},
SubnetsList: []*aws2.Subnet{},
VpcsList: []*aws2.Vpc{},
ResourceModelMetadata: common.ResourceModelMetadata{Version: version.VersionCore, Provider: common.AWS},
ResourceModelMetadata: common.ResourceModelMetadata{Version: version.VersionCore, Provider: string(common.AWS)},
}
}

Expand Down
39 changes: 39 additions & 0 deletions pkg/common/provider.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
Copyright 2023- IBM Inc. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/

package common

import (
"fmt"
"slices"
"strings"
)

type Provider string

const (
AWS Provider = "aws"
IBM Provider = "ibm"
)

var AllProviders = []string{string(IBM), string(AWS)}

func (p *Provider) String() string {
return string(*p)
}

func (p *Provider) Set(v string) error {
v = strings.ToLower(v)
if slices.Contains(AllProviders, v) {
*p = Provider(v)
return nil
}
return fmt.Errorf("must be one of [%s]", strings.Join(AllProviders, ", "))
}

func (p *Provider) Type() string {
return "string"
}
5 changes: 0 additions & 5 deletions pkg/common/resources_container_inf.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,6 @@ SPDX-License-Identifier: Apache-2.0

package common

const (
AWS string = "aws"
IBM string = "ibm"
)

// ResourcesContainerInf is the interface common to all resources containers
type ResourcesContainerInf interface {
CollectResourcesFromAPI() error
Expand Down
Loading

0 comments on commit 7946a88

Please sign in to comment.