Skip to content

Commit

Permalink
list command : add formatting options and tests
Browse files Browse the repository at this point in the history
  • Loading branch information
nam committed Nov 6, 2019
1 parent 53648c3 commit e012d80
Show file tree
Hide file tree
Showing 6 changed files with 202 additions and 21 deletions.
4 changes: 1 addition & 3 deletions api/modelgeneration/modelgeneration.go
Expand Up @@ -69,9 +69,7 @@ func (c *Client) CommitBranch(branchName string) (int, error) {
return result.Result, nil
}

// CommitBranch commits the branch with the input name to the model,
// effectively completing it and applying all branch changes across the model.
// The new generation ID of the model is returned.
// ListCommits lists the committed branches commits,
func (c *Client) ListCommits(formatTime func(time.Time) string) (model.GenerationCommits, error) {
var result params.GenerationResults
err := c.facade.FacadeCall("ListCommits", nil, &result)
Expand Down
17 changes: 11 additions & 6 deletions apiserver/facades/client/modelgeneration/modelgeneration.go
Expand Up @@ -294,17 +294,22 @@ func (api *API) ListCommits() (params.GenerationResults, error) {
if branches, err = api.model.Branches(); err != nil {
return generationResultsError(err)
}
logger.Errorf("branches found %q", branches)

//TODO: check whether branches usage is correct
results := make([]params.Generation, len(branches))
for i, b := range branches {
generation, err := api.oneBranchInfo(b, false)
if err != nil {
return generationResultsError(err)
}
if generation.GenerationId > 0 {
results[i] = generation
if b.GenerationId() > 0 {
gen := params.Generation{
BranchName: b.BranchName(),
Created: b.Created(),
CreatedBy: b.CreatedBy(),
GenerationId: b.GenerationId(),
}
results[i] = gen
}
}
logger.Errorf("results found %q", results)

result.Generations = results
return result, nil
Expand Down
1 change: 1 addition & 0 deletions cmd/juju/commands/main.go
Expand Up @@ -372,6 +372,7 @@ func registerCommands(r commandRegistry, ctx *cmd.Context) {
r.Register(model.NewBranchCommand())
r.Register(model.NewDiffCommand())
r.Register(model.NewAbortCommand())
r.Register(model.NewCommitsCommand())
}

r.Register(newMigrateCommand())
Expand Down
55 changes: 54 additions & 1 deletion cmd/juju/model/listcommits.go
Expand Up @@ -4,12 +4,15 @@
package model

import (
"fmt"
"github.com/gosuri/uitable"
"github.com/juju/cmd"
"github.com/juju/errors"
"github.com/juju/gnuflag"
"github.com/juju/juju/cmd/juju/common"
"github.com/juju/juju/core/model"
"github.com/juju/juju/juju/osenv"
"io"
"os"
"strconv"
"time"
Expand Down Expand Up @@ -82,6 +85,11 @@ func (c *CommitsCommand) Info() *cmd.Info {
func (c *CommitsCommand) SetFlags(f *gnuflag.FlagSet) {
c.ModelCommandBase.SetFlags(f)
f.BoolVar(&c.isoTime, "utc", false, "Display time as UTC in RFC3339 format")
c.out.AddFlags(f, "tabular", map[string]cmd.Formatter{
"yaml": cmd.FormatYaml,
"json": cmd.FormatJson,
"tabular": c.printTabular,
})
}

// Init implements part of the cmd.Command interface.
Expand Down Expand Up @@ -134,5 +142,50 @@ func (c *CommitsCommand) Run(ctx *cmd.Context) error {
if err != nil {
return errors.Trace(err)
}
return errors.Trace(c.out.Write(ctx, commits))
tabular := constructYaml(commits)
return errors.Trace(c.out.Write(ctx, tabular))
}

// printTabular prints the list of actions in tabular format
func (c *CommitsCommand) printTabular(writer io.Writer, value interface{}) error {
list, ok := value.(formattedCommitList)
if !ok {
return errors.New("unexpected value")
}

table := uitable.New()
table.MaxColWidth = 50
table.Wrap = true

table.AddRow("Commit", "Committed at", "Committed by", "Branch name")
for _, c := range list.Commits {
table.AddRow(c.CommitId, c.CommittedAt, c.CommittedBy, c.BranchName)
}
_, _ = fmt.Fprint(writer, table)
return nil
}

func constructYaml(gen model.GenerationCommits) formattedCommitList {
result := formattedCommitList{}
for _, gen := range gen {
fmc := formattedCommit{
CommitId: gen.CommitNumber,
BranchName: gen.BranchName,
CommittedAt: gen.Created,
CommittedBy: gen.CreatedBy,
}
result.Commits = append(result.Commits, fmc)
}
return result
}

type formattedCommit struct {
CommitId int `json:"id" yaml:"id"`
BranchName string `json:"branch-name" yaml:"branch-name"`
CommittedAt string `json:"committed-at" yaml:"committed-at"`
CommittedBy string `json:"committed-by" yaml:"committed-by"`
}

type formattedCommitList struct {
Commits []formattedCommit `json:"commits" yaml:"commits"`
}
82 changes: 71 additions & 11 deletions cmd/juju/model/listcommits_test.go
Expand Up @@ -11,6 +11,7 @@ import (
jc "github.com/juju/testing/checkers"
"github.com/pkg/errors"
gc "gopkg.in/check.v1"
"regexp"

"github.com/juju/juju/cmd/juju/model"
"github.com/juju/juju/cmd/juju/model/mocks"
Expand All @@ -20,7 +21,7 @@ import (
type commitsSuite struct {
generationBaseSuite

api *mocks.MockListCommitsCommandAPI
api *mocks.MockCommitsCommandAPI
}

var _ = gc.Suite(&commitsSuite{})
Expand All @@ -34,29 +35,88 @@ func (s *commitsSuite) TestInitOneArg(c *gc.C) {
err := s.runInit(s.branchName)
c.Assert(err, gc.ErrorMatches, `expected no arguments, but got 1`)
}

func (s *commitsSuite) TestRunCommandNextGenExists(c *gc.C) {
defer s.setup(c).Finish()

result := []coremodel.GenerationCommit{
func (s *commitsSuite) getMockValues() []coremodel.GenerationCommit {
values := []coremodel.GenerationCommit{
{
Created: "0001-01-01 00:00:00Z",
Created: "0001-01-01",
CreatedBy: "test-user",
CommitNumber: 1,
BranchName: "bla",
},
{
Created: "0001-02-02 00:00:00Z",
Created: "0001-02-02",
CreatedBy: "test-user",
CommitNumber: 2,
BranchName: "test",
},
}
return values
}

func (s *commitsSuite) TestRunCommandTabularOutput(c *gc.C) {
defer s.setup(c).Finish()
result := s.getMockValues()
expected :=
"Commit\tCommitted at \tCommitted by\tBranch name" +
"\n1 \t0001-01-01\ttest-user \tbla " +
"\n2 \t0001-02-02\ttest-user \ttest \n"
s.api.EXPECT().ListCommits(gomock.Any()).Return(result, nil)

ctx, err := s.runCommand(c)
c.Assert(err, jc.ErrorIsNil)
c.Assert(cmdtesting.Stdout(ctx), gc.Equals, expected)
}

func (s *commitsSuite) TestRunCommandJsonOutput(c *gc.C) {
defer s.setup(c).Finish()
result := s.getMockValues()
unwrap := regexp.MustCompile(`[\s+\n]`)
expected := unwrap.ReplaceAllLiteralString(`
{
"commits": [
{
"id": 1,
"branch-name": "bla",
"committed-at": "0001-01-01",
"committed-by": "test-user"
},
{
"id": 2,
"branch-name": "test",
"committed-at": "0001-02-02",
"committed-by": "test-user"
}
]
}
`, "")
expected = expected + "\n"
s.api.EXPECT().ListCommits(gomock.Any()).Return(result, nil)

ctx, err := s.runCommand(c, "--format=json")
c.Assert(err, jc.ErrorIsNil)
c.Assert(cmdtesting.Stdout(ctx), gc.Matches, expected)
}

func (s *commitsSuite) TestRunCommandYamlOutput(c *gc.C) {
defer s.setup(c).Finish()
result := s.getMockValues()
expected := `
commits:
- id: 1
branch-name: bla
committed-at: "0001-01-01"
committed-by: test-user
- id: 2
branch-name: test
committed-at: "0001-02-02"
committed-by: test-user
`[1:]
s.api.EXPECT().ListCommits(gomock.Any()).Return(result, nil)

ctx, err := s.runCommand(c, "--format=yaml")
c.Assert(err, jc.ErrorIsNil)
fmt.Println(cmdtesting.Stdout(ctx))
c.Assert(cmdtesting.Stdout(ctx), gc.Matches, expected)
}

func (s *commitsSuite) TestRunCommandAPIError(c *gc.C) {
Expand All @@ -72,13 +132,13 @@ func (s *commitsSuite) runInit(args ...string) error {
return cmdtesting.InitCommand(model.NewListCommitsCommandForTest(nil, s.store), args)
}

func (s *commitsSuite) runCommand(c *gc.C) (*cmd.Context, error) {
return cmdtesting.RunCommand(c, model.NewListCommitsCommandForTest(s.api, s.store))
func (s *commitsSuite) runCommand(c *gc.C, args ...string) (*cmd.Context, error) {
return cmdtesting.RunCommand(c, model.NewListCommitsCommandForTest(s.api, s.store), args...)
}

func (s *commitsSuite) setup(c *gc.C) *gomock.Controller {
ctrl := gomock.NewController(c)
s.api = mocks.NewMockListCommitsCommandAPI(ctrl)
s.api = mocks.NewMockCommitsCommandAPI(ctrl)
s.api.EXPECT().Close()
return ctrl
}
64 changes: 64 additions & 0 deletions cmd/juju/model/mocks/commits_mock.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit e012d80

Please sign in to comment.