diff --git a/README.md b/README.md index ac2a165..5b76307 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ A CLI tool for common tasks relating to the Single Digital Presence hosting plat These commands simplify common cryptographic processes. -*Encrypt secrets to store in the project codebase. +*Encrypt secrets to store in the project codebase.* ``` cat /tmp/oauth.pem | bay kms encrypt \ --project content-foo-vic-gov-au \ @@ -20,3 +20,30 @@ This will store the encrypted file at `keys/production/oauth.pem.asc`. ``` cat oauth.pen.asc | bay kms decrypt > oauth.pem ``` + +## Project Map + +These commands provide a simple way to show how projects relate to eachother. + +*Show all frontends connected a specific backends* + +```sh +bay project-map by-backend content-vic +bay project-map by-backend content-health-vic-gov-au content-legalaid-vic-gov-au +bay project-map by-backend --all --output=json +``` + +*Show which backend a specific frontend connects to* + +```sh +bay project-map by-frontend vic-gov-au +bay project-map by-frontend --all +``` + +### Outputs + +These commands accept a `--output` flag which can be one of the following values: + +* `json` - a json object +* `table` - a cli table +* `go-template-file` - accepts another flag `--go-template-file` which indicates a go template to use for output. See `examples/templates` for ways to use this. \ No newline at end of file diff --git a/cmd/project-map/by-backend.go b/cmd/project-map/by-backend.go index 6fbb2ea..ae0cf8f 100644 --- a/cmd/project-map/by-backend.go +++ b/cmd/project-map/by-backend.go @@ -3,13 +3,17 @@ package project_map import ( "encoding/json" "fmt" + "github.com/pkg/errors" + "path" "strings" + "text/template" "github.com/alexeyco/simpletable" "github.com/urfave/cli/v2" "github.com/uselagoon/machinery/api/schema" "github.com/dpc-sdp/bay-cli/internal/helpers" + template_helpers "github.com/dpc-sdp/bay-cli/internal/template" ) type ByBackendResponse struct { @@ -21,6 +25,11 @@ type ByBackendResponseItem struct { FrontEnds []string `json:"frontends"` } +type ByBackendTemplateVars struct { + Inventory map[string]schema.Project + Items []ByBackendResponseItem +} + func ByBackend(c *cli.Context) error { client, err := helpers.NewLagoonClient(nil) if err != nil { @@ -28,6 +37,7 @@ func ByBackend(c *cli.Context) error { } output := ByBackendResponse{} + projectInventory := make(map[string]schema.Project) all := c.Bool("all") args := make([]string, 0) @@ -39,17 +49,20 @@ func ByBackend(c *cli.Context) error { } for _, p := range projects { args = append(args, p.Name) + + projectInventory[p.Name] = p.Project } } else { args = helpers.GetAllArgs(c) } for _, v := range args { - project := &schema.ProjectMetadata{} - err := client.ProjectByNameMetadata(c.Context, v, project) + project := &schema.Project{} + err := client.ProjectByNameExtended(c.Context, v, project) if err != nil { return err } + projectInventory[project.Name] = *project projects := make([]schema.ProjectMetadata, 0) err = client.ProjectsByMetadata(c.Context, "backend-project", v, &projects) @@ -64,14 +77,38 @@ func ByBackend(c *cli.Context) error { for _, p := range projects { item.FrontEnds = append(item.FrontEnds, p.Name) + projectInventory[p.Name] = p.Project } output.Items = append(output.Items, item) } - if c.String("output") == "json" { + // JSON output + outputFormat := c.String("output") + if outputFormat == "json" { a, _ := json.Marshal(output) fmt.Fprintf(c.App.Writer, string(a)) + } else if outputFormat == "go-template-file" { + pathOnDisk := c.String("go-template-file") + basePath := path.Base(pathOnDisk) + if pathOnDisk == "" { + return fmt.Errorf("--go-template-file flag was empty, but is a required field when using the --output=go-template-file option") + } + templateInputs := ByBackendTemplateVars{ + Inventory: projectInventory, + Items: output.Items, + } + + tmpl, err := template.New(basePath).Funcs(template.FuncMap{ + "convert_github_url_to_page": template_helpers.ConvertGithubUriToPage, + }).ParseFiles(pathOnDisk) + if err != nil { + return errors.Wrap(err, "could not load template file") + } + err = tmpl.Execute(c.App.Writer, templateInputs) + if err != nil { + return errors.Wrap(err, "could not render template") + } } else { table := simpletable.New() @@ -89,7 +126,7 @@ func ByBackend(c *cli.Context) error { } table.Body.Cells = append(table.Body.Cells, r) } - table.SetStyle(simpletable.StyleCompactLite) + table.SetStyle(simpletable.StyleMarkdown) fmt.Fprintf(c.App.Writer, table.String()) } diff --git a/cmd/project-map/by-frontend.go b/cmd/project-map/by-frontend.go index 34eadf6..6bff7c8 100644 --- a/cmd/project-map/by-frontend.go +++ b/cmd/project-map/by-frontend.go @@ -3,17 +3,27 @@ package project_map import ( "encoding/json" "fmt" + "path" + "text/template" + "github.com/alexeyco/simpletable" + "github.com/pkg/errors" "github.com/urfave/cli/v2" "github.com/uselagoon/machinery/api/schema" "github.com/dpc-sdp/bay-cli/internal/helpers" + template_helpers "github.com/dpc-sdp/bay-cli/internal/template" ) type ByFrontendResponse struct { Items map[string]string `json:"items"` } +type ByFrontendTemplateVars struct { + Inventory map[string]schema.Project + Items map[string]string +} + func ByFrontend(c *cli.Context) error { client, err := helpers.NewLagoonClient(nil) if err != nil { @@ -23,6 +33,7 @@ func ByFrontend(c *cli.Context) error { output := ByFrontendResponse{ Items: make(map[string]string, 0), } + projectInventory := make(map[string]schema.Project) all := c.Bool("all") args := make([]string, 0) @@ -35,6 +46,7 @@ func ByFrontend(c *cli.Context) error { } for _, p := range rippleProjects { args = append(args, p.Name) + projectInventory[p.Name] = p.Project } ripple2Projects := make([]schema.ProjectMetadata, 0) @@ -44,18 +56,22 @@ func ByFrontend(c *cli.Context) error { } for _, p := range ripple2Projects { args = append(args, p.Name) + projectInventory[p.Name] = p.Project } } else { args = helpers.GetAllArgs(c) } for _, v := range args { - project := &schema.ProjectMetadata{} - - err := client.ProjectByNameMetadata(c.Context, v, project) - if err != nil { - return err + if _, ok := projectInventory[v]; !ok { + project := &schema.ProjectMetadata{} + err := client.ProjectByNameMetadata(c.Context, v, project) + if err != nil { + return err + } + projectInventory[v] = project.Project } + if err != nil { return err } @@ -63,9 +79,32 @@ func ByFrontend(c *cli.Context) error { output.Items[v] = project.Metadata["backend-project"] } - if c.String("output") == "json" { + outputFormat := c.String("output") + if outputFormat == "json" { a, _ := json.Marshal(output) fmt.Fprintf(c.App.Writer, string(a)) + } else if outputFormat == "go-template-file" { + pathOnDisk := c.String("go-template-file") + basePath := path.Base(pathOnDisk) + if pathOnDisk == "" { + return fmt.Errorf("--go-template-file flag was empty, but is a required field when using the --output=go-template-file option") + } + + templateInputs := ByFrontendTemplateVars{ + Items: output.Items, + Inventory: + } + + tmpl, err := template.New(basePath).Funcs(template.FuncMap{ + "convert_github_url_to_page": template_helpers.ConvertGithubUriToPage, + }).ParseFiles(pathOnDisk) + if err != nil { + return errors.Wrap(err, "could not load template file") + } + err = tmpl.Execute(c.App.Writer, templateInputs) + if err != nil { + return errors.Wrap(err, "could not render template") + } } else { table := simpletable.New() diff --git a/examples/templates/project-map-by-backend-table.tmpl b/examples/templates/project-map-by-backend-table.tmpl new file mode 100644 index 0000000..21382f2 --- /dev/null +++ b/examples/templates/project-map-by-backend-table.tmpl @@ -0,0 +1,34 @@ +{{ $inventory := .Inventory }} +
|
+ Backend + |
+ + Frontends + | +
|---|---|
|
+ {{ with (index $inventory $item.Project)}}
+ |
+
+
|
+