-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add command line tool to query / upload to terrarium (#62)
* Initial commit of CLI * Delete cli * Unit tests * Add code to publish a module * Add better error handling and improve container deps output * Add module-deps command * Add publish command * Update module_publish.go * Delete LICENSE * Tidy up * Ensure cli is build on PR * Update pr.yml * Update pr.yml * Update module_publish.go * Remove copyright comment
- Loading branch information
Showing
14 changed files
with
848 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
cli |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package cmd | ||
|
||
import ( | ||
"github.com/spf13/cobra" | ||
"github.com/terrariumcloud/terrarium/pkg/terrarium/module" | ||
"google.golang.org/grpc" | ||
"google.golang.org/grpc/credentials/insecure" | ||
) | ||
|
||
// moduleCmd represents the module command | ||
var moduleCmd = &cobra.Command{ | ||
Use: "module", | ||
Short: "Commands for managing modules", | ||
} | ||
|
||
func init() { | ||
rootCmd.AddCommand(moduleCmd) | ||
} | ||
|
||
func getModulePublisherClient() (*grpc.ClientConn, module.PublisherClient, error) { | ||
conn, err := grpc.Dial(terrariumEndpoint, grpc.WithTransportCredentials(insecure.NewCredentials())) | ||
if err != nil { | ||
return nil, nil, err | ||
} | ||
return conn, module.NewPublisherClient(conn), nil | ||
} | ||
|
||
func getModuleConsumerClient() (*grpc.ClientConn, module.ConsumerClient, error) { | ||
conn, err := grpc.Dial(terrariumEndpoint, grpc.WithTransportCredentials(insecure.NewCredentials())) | ||
if err != nil { | ||
return nil, nil, err | ||
} | ||
return conn, module.NewConsumerClient(conn), nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
package cmd | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"github.com/spf13/cobra" | ||
"github.com/terrariumcloud/terrarium/pkg/terrarium/module" | ||
"io" | ||
) | ||
|
||
// containerDepsCmd represents the containerDeps command | ||
var containerDepsCmd = &cobra.Command{ | ||
Use: "container-deps", | ||
Short: "List the container dependencies for a module", | ||
Args: cobra.ExactArgs(2), | ||
Run: func(cmd *cobra.Command, args []string) { | ||
conn, client, err := getModuleConsumerClient() | ||
if err != nil { | ||
printErrorAndExit("Failed to connect to terrarium", err, 1) | ||
} | ||
defer func() { _ = conn.Close() }() | ||
req := module.RetrieveContainerDependenciesRequestV2{ | ||
Module: &module.Module{ | ||
Name: args[0], | ||
Version: args[1], | ||
}, | ||
} | ||
responseClient, err := client.RetrieveContainerDependenciesV2(context.Background(), &req) | ||
if err != nil { | ||
printErrorAndExit("Failed to retrieve container dependencies", err, 1) | ||
} | ||
for { | ||
response, err := responseClient.Recv() | ||
if err == io.EOF { | ||
break | ||
} | ||
if err != nil { | ||
printErrorAndExit("Retrieving dependencies failed", err, 1) | ||
} | ||
fmt.Printf("%s:%s:\n", response.Module.Name, response.Module.Version) | ||
for name, containerDetails := range response.Dependencies { | ||
fmt.Printf(" %s/%s:%s:\n", containerDetails.Namespace, name, containerDetails.Tag) | ||
|
||
for _, details := range containerDetails.Images { | ||
fmt.Printf(" - arch: %s\n", details.Arch) | ||
fmt.Printf(" image: %s\n", details.Image) | ||
} | ||
} | ||
} | ||
}, | ||
} | ||
|
||
func init() { | ||
moduleCmd.AddCommand(containerDepsCmd) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
package cmd | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"github.com/spf13/cobra" | ||
"github.com/terrariumcloud/terrarium/pkg/terrarium/module" | ||
"io" | ||
) | ||
|
||
// moduleDepsCmd represents the moduleDeps command | ||
var moduleDepsCmd = &cobra.Command{ | ||
Use: "module-deps", | ||
Short: "List the module dependencies of the specified module.", | ||
Args: cobra.ExactArgs(2), | ||
Run: func(cmd *cobra.Command, args []string) { | ||
conn, client, err := getModuleConsumerClient() | ||
if err != nil { | ||
printErrorAndExit("Failed to connect to terrarium", err, 1) | ||
} | ||
defer func() { _ = conn.Close() }() | ||
req := module.RetrieveModuleDependenciesRequest{ | ||
Module: &module.Module{ | ||
Name: args[0], | ||
Version: args[1], | ||
}, | ||
} | ||
responseClient, err := client.RetrieveModuleDependencies(context.Background(), &req) | ||
if err != nil { | ||
printErrorAndExit("Failed to retrieve module dependencies", err, 1) | ||
} | ||
for { | ||
response, err := responseClient.Recv() | ||
if err == io.EOF { | ||
break | ||
} | ||
if err != nil { | ||
printErrorAndExit("Retrieving dependencies failed", err, 1) | ||
} | ||
fmt.Printf("%s:%s:\n", response.Module.Name, response.Module.Version) | ||
for _, module := range response.Dependencies { | ||
fmt.Printf(" - %s:%s\n", module.Name, module.Version) | ||
} | ||
} | ||
}, | ||
} | ||
|
||
func init() { | ||
moduleCmd.AddCommand(moduleDepsCmd) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
package cmd | ||
|
||
import ( | ||
"fmt" | ||
module2 "github.com/terrariumcloud/terrarium/pkg/terrarium/module" | ||
"github.com/terrariumcloud/terrarium/tools/cli/pkg/module" | ||
"os" | ||
"strings" | ||
|
||
"github.com/spf13/cobra" | ||
) | ||
|
||
type maturityValue struct { | ||
maturity module2.Maturity | ||
} | ||
|
||
var ( | ||
moduleMetadata = module.Metadata{ | ||
Name: "", | ||
Version: "", | ||
Description: "", | ||
Source: "", | ||
Maturity: module2.Maturity_STABLE, | ||
} | ||
maturityVar = maturityValue{maturity: module2.Maturity_STABLE} | ||
) | ||
|
||
// modulePublishCmd represents the publish command | ||
var modulePublishCmd = &cobra.Command{ | ||
Use: "publish [module source.zip]", | ||
Short: "Publishes a zip file as a module version in terrarium.", | ||
Args: cobra.ExactArgs(1), | ||
Run: func(cmd *cobra.Command, args []string) { | ||
conn, client, err := getModulePublisherClient() | ||
if err != nil { | ||
printErrorAndExit("Failed to connect to terrarium", err, 1) | ||
} | ||
defer func() { _ = conn.Close() }() | ||
if source, err := os.Open(args[0]); err != nil { | ||
printErrorAndExit(fmt.Sprintf("Failed to open %s", args[0]), err, 1) | ||
} else { | ||
moduleMetadata.Maturity = maturityVar.maturity | ||
err := module.Publish(client, source, moduleMetadata) | ||
if err != nil { | ||
printErrorAndExit("Publishing module failed", err, 1) | ||
} else { | ||
fmt.Println("Module published.") | ||
} | ||
} | ||
}, | ||
} | ||
|
||
func init() { | ||
moduleCmd.AddCommand(modulePublishCmd) | ||
|
||
modulePublishCmd.Flags().StringVar(&moduleMetadata.Name, "name", "", "Name of the module in the form \"<organisation>/<name>/<provider>\".") | ||
_ = modulePublishCmd.MarkFlagRequired("name") | ||
modulePublishCmd.Flags().StringVar(&moduleMetadata.Version, "version", "", "Semantic version of the module to publish.") | ||
_ = modulePublishCmd.MarkFlagRequired("version") | ||
modulePublishCmd.Flags().StringVar(&moduleMetadata.Description, "description", "", "Description of the module.") | ||
modulePublishCmd.Flags().StringVar(&moduleMetadata.Source, "source", "", "URL containing the module source.") | ||
modulePublishCmd.Flags().Var(&maturityVar, "maturity", "The maturity of the module, one of IDEA, PLANNING, DEVELOPING, ALPHA, BETA, STABLE, DEPRECATED or END-OF-LIFE.") | ||
} | ||
|
||
var maturityToString = map[module2.Maturity]string{ | ||
module2.Maturity_IDEA: "IDEA", | ||
module2.Maturity_PLANNING: "PLANNING", | ||
module2.Maturity_DEVELOPING: "DEVELOPING", | ||
module2.Maturity_ALPHA: "ALPHA", | ||
module2.Maturity_BETA: "BETA", | ||
module2.Maturity_STABLE: "STABLE", | ||
module2.Maturity_DEPRECATED: "DEPRECATED", | ||
module2.Maturity_END_OF_LIFE: "END-OF-LIFE", | ||
} | ||
|
||
func (m maturityValue) String() string { | ||
if s, ok := maturityToString[m.maturity]; ok { | ||
return s | ||
} | ||
return "UNKNOWN" | ||
} | ||
|
||
func (m *maturityValue) Set(s string) error { | ||
for maturity, maturityStr := range maturityToString { | ||
if strings.ToUpper(s) == maturityStr { | ||
m.maturity = maturity | ||
return nil | ||
} | ||
} | ||
return fmt.Errorf("unknown maturity: %s", s) | ||
} | ||
|
||
func (m maturityValue) Type() string { | ||
return "maturity" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
package cmd | ||
|
||
import ( | ||
"github.com/terrariumcloud/terrarium/pkg/terrarium/release" | ||
"google.golang.org/grpc" | ||
"google.golang.org/grpc/credentials/insecure" | ||
|
||
"github.com/spf13/cobra" | ||
) | ||
|
||
// releaseCmd represents the release command | ||
var releaseCmd = &cobra.Command{ | ||
Use: "release", | ||
Short: "Commands for managing releases", | ||
} | ||
|
||
func init() { | ||
rootCmd.AddCommand(releaseCmd) | ||
} | ||
|
||
func getReleasePublisherClient() (*grpc.ClientConn, release.ReleasePublisherClient, error) { | ||
conn, err := grpc.Dial(terrariumEndpoint, grpc.WithTransportCredentials(insecure.NewCredentials())) | ||
if err != nil { | ||
return nil, nil, err | ||
} | ||
return conn, release.NewReleasePublisherClient(conn), nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
package cmd | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"github.com/spf13/cobra" | ||
"github.com/terrariumcloud/terrarium/pkg/terrarium/release" | ||
"strings" | ||
) | ||
|
||
var ( | ||
releaseToPublish = release.PublishRequest{ | ||
Type: "", | ||
Organization: "", | ||
Name: "", | ||
Version: "", | ||
Description: "", | ||
Links: nil, | ||
} | ||
releaseLinks []string | ||
) | ||
|
||
// releasePublishCmd represents the publish command | ||
var releasePublishCmd = &cobra.Command{ | ||
Use: "publish", | ||
Short: "Publish details of a new release.", | ||
Run: func(cmd *cobra.Command, args []string) { | ||
conn, client, err := getReleasePublisherClient() | ||
if err != nil { | ||
printErrorAndExit("Failed to connect to terrarium", err, 1) | ||
} | ||
defer func() { _ = conn.Close() }() | ||
|
||
for _, link := range releaseLinks { | ||
if parts := strings.SplitN(link, "=", 2); len(parts) == 1 { | ||
releaseToPublish.Links = append(releaseToPublish.Links, &release.Link{ | ||
Title: "", | ||
Url: parts[0], | ||
}) | ||
} else { | ||
releaseToPublish.Links = append(releaseToPublish.Links, &release.Link{ | ||
Title: parts[0], | ||
Url: parts[1], | ||
}) | ||
} | ||
} | ||
|
||
if _, err := client.Publish(context.Background(), &releaseToPublish); err != nil { | ||
printErrorAndExit("Failed to publish release", err, 1) | ||
} | ||
fmt.Println("Release published.") | ||
}, | ||
} | ||
|
||
func init() { | ||
releaseCmd.AddCommand(releasePublishCmd) | ||
releasePublishCmd.Flags().StringVarP(&releaseToPublish.Name, "name", "n", "", "Name of the release.") | ||
releasePublishCmd.MarkFlagRequired("name") | ||
releasePublishCmd.Flags().StringVarP(&releaseToPublish.Version, "version", "v", "", "Version of the release.") | ||
releasePublishCmd.MarkFlagRequired("version") | ||
releasePublishCmd.Flags().StringVarP(&releaseToPublish.Organization, "org", "o", "", "Organization to which the release belongs.") | ||
releasePublishCmd.MarkFlagRequired("org") | ||
releasePublishCmd.Flags().StringVarP(&releaseToPublish.Type, "type", "t", "", "Type of release.") | ||
releasePublishCmd.MarkFlagRequired("type") | ||
releasePublishCmd.Flags().StringVarP(&releaseToPublish.Description, "description", "d", "", "Description of the release being published.") | ||
releasePublishCmd.Flags().StringSliceVarP(&releaseLinks, "link", "l", []string{}, `Links and optional titles eg.: --link "title=url" or --link "url"`) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
package cmd | ||
|
||
import ( | ||
"fmt" | ||
"os" | ||
|
||
"github.com/spf13/cobra" | ||
) | ||
|
||
var terrariumEndpoint = "localhost:3001" | ||
|
||
// rootCmd represents the base command when called without any subcommands | ||
var rootCmd = &cobra.Command{ | ||
Use: "cli", | ||
Short: "A brief description of your application", | ||
Long: `A longer description that spans multiple lines and likely contains | ||
examples and usage of using your application. For example: | ||
Cobra is a CLI library for Go that empowers applications. | ||
This application is a tool to generate the needed files | ||
to quickly create a Cobra application.`, | ||
} | ||
|
||
// Execute adds all child commands to the root command and sets flags appropriately. | ||
// This is called by main.main(). It only needs to happen once to the rootCmd. | ||
func Execute() { | ||
err := rootCmd.Execute() | ||
if err != nil { | ||
os.Exit(1) | ||
} | ||
} | ||
|
||
func init() { | ||
rootCmd.PersistentFlags().StringVar(&terrariumEndpoint, "endpoint", terrariumEndpoint, "GRPC Endpoint for Terrarium.") | ||
} | ||
|
||
func printErrorAndExit(msg string, err error, exitCode int) { | ||
fmt.Fprintf(os.Stderr, "ERROR: %s", msg) | ||
if err != nil { | ||
fmt.Fprintf(os.Stderr, ": %s\n", err) | ||
} else { | ||
fmt.Fprintln(os.Stderr, "") | ||
} | ||
os.Exit(exitCode) | ||
} |
Oops, something went wrong.