Skip to content

Add multiple output printer formats - #22

Merged
Cody A. Ray (codyaray) merged 9 commits into
masterfrom
printer
May 30, 2018
Merged

Add multiple output printer formats#22
Cody A. Ray (codyaray) merged 9 commits into
masterfrom
printer

Conversation

@codyaray

@codyaray Cody A. Ray (codyaray) commented May 29, 2018

Copy link
Copy Markdown
Contributor

We'd like to be able to support -o yaml, -o json, -o wide, etc. Much like kubectl does.

Specifically,

  1. we want to limit the fields we print and, in some cases, rename them to something friendlier
  2. we don't want to define a new struct for each CLI "view" (so have to use reflection)
  3. we want the string form of protobuf enums, not the ordinal form (so have to workaround protobufs)

I used the retag library for #1 and #2. Basically, I just change the struct tag to the new name/label or to "-" to drop it from the view.

But retag doesn't work for #3 since it just uses the actual struct field type (which is int32 for enums). So I forked the library to make it a bit more generic so we can actually change the struct field type as well. Of course, this makes the structs not in-memory compatible but that doesn't matter as long as you make a copy instead of just trying to update the original pointer.

This makes creating a new CLI view very simple. Just pass the fields you want, labels you want (for renaming fields), and the desired output format:

if err = common.Render(cluster, describeFields, describeLabels, outputFormat); err != nil {
	return common.HandleError(err)
}

Here's how it looks for a connect cluster (both JSON and YAML):

$ go run main.go connect get connectcli -o json
{
  "Name": "connectcli",
  "Kind": "S3_SINK",
  "Kafka": "cp153",
  "Status": "UP",
  "Durability": "LOW",
  "Provider": "aws",
  "Region": "us-west-2"
}

Cody-Rays-MBP15:cli cody$ go run main.go connect get connectcli -o yaml
Durability: LOW
Kafka: cp153
Kind: S3_SINK
Name: connectcli
Provider: aws
Region: us-west-2
Status: UP

Comment thread command/common/output.go Outdated
RenderDetail(obj, fields, labels)
case "json":
if msg, ok := obj.(proto.Message); ok {
m := jsonpb.Marshaler{Indent: " "}

@travisjeffery Travis Jeffery (travisjeffery) May 29, 2018

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@travisjeffery

Travis Jeffery (travisjeffery) commented May 29, 2018

Copy link
Copy Markdown
Contributor

type per view would be a lot simpler, cleaner, flexible. add a dash of generating to save the duping if necessary.

@chicagobuss Joshua Buss (chicagobuss) left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm, but could you make a test or two to make sure you're getting the output you expect?

Comment thread command/common/output.go

func (f *enumStringifyingFieldMaker) MakeField(oldType reflect.Type, newType reflect.Type, oldTag reflect.StructTag, newTag reflect.StructTag) (reflect.Type, reflect.StructTag) {
if strings.Contains(string(oldTag), "protobuf:") && strings.Contains(string(oldTag), "enum=") {
newType = reflect.TypeOf("")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

surely there's an easier way to get a string type?

Comment thread command/common/output.go

type enumStringifyingFieldMaker struct{}

func (f *enumStringifyingFieldMaker) MakeField(oldType reflect.Type, newType reflect.Type, oldTag reflect.StructTag, newTag reflect.StructTag) (reflect.Type, reflect.StructTag) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would like a walkthrough of how exactly this works sometime...

Comment thread command/common/output.go

// Helper which stringifies protobuf enum fields.
// Implemented by returning an anonymous dynamic struct with string field type in place of enum fields.
func prepareProtoStruct(msg proto.Message, fields []string) interface{} {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yah, I think I needed this in the last app I was trying to make, too

@codyaray

Copy link
Copy Markdown
Contributor Author

Joshua Buss (@chicagobuss) tests added. bugs fixed

@codyaray
Cody A. Ray (codyaray) merged commit 1cca75c into master May 30, 2018
@codyaray
Cody A. Ray (codyaray) deleted the printer branch May 30, 2018 03:09
Brian Strauch (brianstrauch) pushed a commit that referenced this pull request May 31, 2023
* chore: reset mk-include

* Squashed 'mk-include/' content from commit 040d48f

git-subtree-dir: mk-include
git-subtree-split: 040d48f663b65e28ed3463e4bffe2e4b52f4a2f4

* chore: add mk-include-git-hash

---------

Co-authored-by: Confluent Jenkins Bot <jenkins@confluent.io>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants