-
Notifications
You must be signed in to change notification settings - Fork 903
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Complete tags management APIs #1162
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking good @jiatongw
Note that several of my comments apply to all commands.
govc/tags/association/attach.go
Outdated
} | ||
|
||
func (cmd *attach) Description() string { | ||
return ` Attach tag to object. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Leading space should be removed.
govc/tags/association/attach.go
Outdated
return "", "", fmt.Errorf("%s not found", managedObj) | ||
case 1: | ||
ref = l[0].Object.Reference() | ||
s := strings.Split(ref.String(), ":") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can use ref.Type
and ref.Value
here, rather than splitting the String()
. This function could also just return types.ManagedObjectReference
instead of the 2 strings.
govc/tags/association/attach.go
Outdated
return "", "", flag.ErrHelp | ||
} | ||
} else { | ||
s := strings.Split(managedObj, ":") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same comment as above, no need to Split.
govc/tags/association/attach.go
Outdated
) | ||
|
||
type attach struct { | ||
*flags.ClientFlag |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can remove this line, since DatacenterFlag
already embeds a ClientFlag
.
govc/tags/association/attach.go
Outdated
} | ||
|
||
func (cmd *attach) Register(ctx context.Context, f *flag.FlagSet) { | ||
cmd.ClientFlag, ctx = flags.NewClientFlag(ctx) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And remove these 2 ClientFlag
lines, as the DatacenterFlag.Register
below takes care of this.
govc/tags/tags/get.go
Outdated
|
||
func (r getTagName) Write(w io.Writer) error { | ||
for i := range r { | ||
fmt.Fprintln(w, r[i]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since tags.Tag
is a structure rather than just a string
, the Write
command should use TabWriter to format the output.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Example:
Lines 69 to 75 in b325163
tw := tabwriter.NewWriter(w, 2, 0, 2, ' ', 0) | |
for _, role := range rl { | |
fmt.Fprintf(tw, "%s\t%s\n", role.Name, role.Info.GetDescription().Summary) | |
} | |
return tw.Flush() |
vapi/tags/tag_association.go
Outdated
return &spec | ||
} | ||
|
||
func (c *RestClient) AttachTagToObject(ctx context.Context, tagID string, objID string, objType string) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For these methods, instead of tagID
and objID
as string inputs, can we use 1 input types.ManagedObjectReference
instead?
vapi/tags/tag_association.go
Outdated
_, _, status, err := c.call(ctx, "POST", fmt.Sprintf("%s?~action=attach", TagAssociationURL), *spec, nil) | ||
|
||
if status != http.StatusOK || err != nil { | ||
return fmt.Errorf("Attach tag failed with status code: %d, error message: %s", status, err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"Error strings should not be capitalized ..." https://github.com/golang/go/wiki/CodeReviewComments#error-strings
vapi/tags/tags.go
Outdated
} | ||
|
||
func (c *RestClient) CreateTag(ctx context.Context, spec *TagCreateSpec) (*string, error) { | ||
stream, _, status, err := c.call(ctx, "POST", TagURL, spec, nil) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could use the http.MethodPost
constant instead of literal "POST"
, same for the other http methods.
vapi/tags/tags.go
Outdated
if err != nil { | ||
return err | ||
} | ||
if objs != nil && len(objs) > 0 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need to check objs != nil
here, len()
will return 0
if objs is nil.
govc/tags/tags/get.go
Outdated
if err != nil { | ||
return err | ||
} | ||
fmt.Println(*tag) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The TabWriter function works well with []tags.Tag type. But cannot use to type *tag. (the Writer function inside there is a loop, which cannot range over that type..) Any suggestions? @dougm
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need to use tabwriter when there would only be 1 row, which seems to be the case here. I think you can just do something space delimited like: fmt.Println(tag.ID, tag.Name, tag.Description, tag.OtherField)
Add tags/association/ and tags/tags/ folder. Add import packages in main.go. Add two tags helper files to vapi/.
…ant code Use tabWriter to output a struct, move govc/tags/tags/ files to govc/tags/, remove ClientFlags register and Process() function in which DatecenterFlag is set, use http.Method to replace "GET", "POST", "DELETE", "PATCH" in vapi/tags/ files.
govc/tags/association/attach.go
Outdated
return `Attach tag to object. | ||
|
||
Examples: | ||
govc tags.attach ID PATH` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you also use example values for the Examples
sections? Instead of PATH
for example, /dc1/host/cluster1/hostname
govc/tags/create.go
Outdated
} | ||
|
||
func (cmd *create) Description() string { | ||
return ` Create tag. This command will output the ID you just created. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove leading space. Add newline after summary.
govc/tags/get.go
Outdated
tw := tabwriter.NewWriter(w, 2, 0, 2, ' ', 0) | ||
|
||
for _, item := range t { | ||
fmt.Fprintf(tw, "Name: %s\nID: %s\nDescription: %s\nCategoryID: %s\nUsedBy: %s\n", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There needs to be tab delimiters (\t
) for tabwriter. Have a look at the existing govc/*/info.go
commands. Speaking of which, this command should probably named tags.info
rather than tags.get
. You'll see we have many *.info
commands that are similar, but we have not commands named get
.
govc/tags/get.go
Outdated
if err != nil { | ||
return err | ||
} | ||
fmt.Printf("Name: %s\nID: %s\nDescription: %s\nCategoryID: %s\nUsedBy: %s\n", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can use the same output formatter in this case. For example the code could be changed to only call WriteResult
in both cases:
var result []tags.Tag
if cmd.name == "" {
tag, err := c.GetTag(ctx, id)
if err != nil {
return err
}
result = append(result, tag)
} else {
tagSlice, err := c.GetTagByNameForCategory(ctx, cmd.name, id)
if err != nil {
return err
}
result = getTagName(tagSlice)
}
return cmd.WriteResult(result)
govc/tags/info.go
Outdated
fmt.Fprintf(tw, " ID:\t%s\n", item.ID) | ||
fmt.Fprintf(tw, " Description:\t%s\n", item.Description) | ||
fmt.Fprintf(tw, " CategoryID:\t%s\n", item.CategoryID) | ||
fmt.Fprintf(tw, " UsedBy: %s\n", item.UsedBy) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Separate fmt.Fprintf() for readable and matching other govc/*/info.go code style
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm, thanks @jiatongw
Tags management in govc has 3 steps: 1. Creating tag category. 2. Creating tag. 3.Attaching created tag. This PR is related with the second and last steps.
The tags management issue can be found here #1139