Skip to content

chore: remove organization requirement from convertGroup() #12195

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

Merged
merged 12 commits into from
Feb 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion cli/clitest/golden.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,11 @@ func prepareTestData(t *testing.T) (*codersdk.Client, map[string]string) {
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
defer cancel()

db, pubsub := dbtestutil.NewDB(t)
// This needs to be a fixed timezone because timezones increase the length
// of timestamp strings. The increased length can pad table formatting's
// and differ the table header spacings.
//nolint:gocritic
db, pubsub := dbtestutil.NewDB(t, dbtestutil.WithTimezone("UTC"))
rootClient := coderdtest.New(t, &coderdtest.Options{
Database: db,
Pubsub: pubsub,
Expand Down
2 changes: 1 addition & 1 deletion cli/cliui/output.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ func TableFormat(out any, defaultColumns []string) OutputFormat {
}

// Get the list of table column headers.
headers, defaultSort, err := typeToTableHeaders(v.Type().Elem())
headers, defaultSort, err := typeToTableHeaders(v.Type().Elem(), true)
if err != nil {
panic("parse table headers: " + err.Error())
}
Expand Down
21 changes: 17 additions & 4 deletions cli/cliui/table.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ func DisplayTable(out any, sort string, filterColumns []string) (string, error)
}

// Get the list of table column headers.
headersRaw, defaultSort, err := typeToTableHeaders(v.Type().Elem())
headersRaw, defaultSort, err := typeToTableHeaders(v.Type().Elem(), true)
if err != nil {
return "", xerrors.Errorf("get table headers recursively for type %q: %w", v.Type().Elem().String(), err)
}
Expand Down Expand Up @@ -230,7 +230,11 @@ func isStructOrStructPointer(t reflect.Type) bool {
// typeToTableHeaders converts a type to a slice of column names. If the given
// type is invalid (not a struct or a pointer to a struct, has invalid table
// tags, etc.), an error is returned.
func typeToTableHeaders(t reflect.Type) ([]string, string, error) {
//
// requireDefault is only needed for the root call. This is recursive, so nested
// structs do not need the default sort name.
// nolint:revive
func typeToTableHeaders(t reflect.Type, requireDefault bool) ([]string, string, error) {
if !isStructOrStructPointer(t) {
return nil, "", xerrors.Errorf("typeToTableHeaders called with a non-struct or a non-pointer-to-a-struct type")
}
Expand All @@ -246,6 +250,12 @@ func typeToTableHeaders(t reflect.Type) ([]string, string, error) {
if err != nil {
return nil, "", xerrors.Errorf("parse struct tags for field %q in type %q: %w", field.Name, t.String(), err)
}

if name == "" && (recursive && skip) {
return nil, "", xerrors.Errorf("a name is required for the field %q. "+
"recursive_line will ensure this is never shown to the user, but is still needed", field.Name)
}
// If recurse and skip is set, the name is intentionally empty.
if name == "" {
continue
}
Expand All @@ -262,7 +272,7 @@ func typeToTableHeaders(t reflect.Type) ([]string, string, error) {
return nil, "", xerrors.Errorf("field %q in type %q is marked as recursive but does not contain a struct or a pointer to a struct", field.Name, t.String())
}

childNames, _, err := typeToTableHeaders(fieldType)
childNames, defaultSort, err := typeToTableHeaders(fieldType, false)
if err != nil {
return nil, "", xerrors.Errorf("get child field header names for field %q in type %q: %w", field.Name, fieldType.String(), err)
}
Expand All @@ -273,13 +283,16 @@ func typeToTableHeaders(t reflect.Type) ([]string, string, error) {
}
headers = append(headers, fullName)
}
if defaultSortName == "" {
defaultSortName = defaultSort
}
continue
}

headers = append(headers, name)
}

if defaultSortName == "" {
if defaultSortName == "" && requireDefault {
return nil, "", xerrors.Errorf("no field marked as default_sort in type %q", t.String())
}

Expand Down
4 changes: 2 additions & 2 deletions cli/cliui/table_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,12 @@ type tableTest2 struct {

type tableTest3 struct {
NotIncluded string // no table tag
Sub tableTest2 `table:"inner,recursive,default_sort"`
Sub tableTest2 `table:"inner,recursive"`
}

type tableTest4 struct {
Inline tableTest2 `table:"ignored,recursive_inline"`
SortField string `table:"sort_field,default_sort"`
SortField string `table:"sort_field"`
}

func Test_DisplayTable(t *testing.T) {
Expand Down
4 changes: 4 additions & 0 deletions cli/root_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ func TestCommandHelp(t *testing.T) {
Name: "coder users list --output json",
Cmd: []string{"users", "list", "--output", "json"},
},
clitest.CommandHelpCase{
Name: "coder users list",
Cmd: []string{"users", "list"},
},
))
}

Expand Down
3 changes: 3 additions & 0 deletions cli/testdata/coder_users_list.golden
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
USERNAME EMAIL CREATED AT STATUS
testuser testuser@coder.com [timestamp] active
Copy link
Member

Choose a reason for hiding this comment

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

Can we replace it with the same length string? Worried someone might think this is a bug. 😄

Copy link
Member Author

Choose a reason for hiding this comment

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

I can pad the timestamp in the replace function?

I could do something like this here:

func NormalizeGoldenFile(t *testing.T, byt []byte) []byte {

	// Replace any timestamps with a placeholder.
	byt = timestampRegex.ReplaceAllFunc(byt, func(source []byte) []byte {
		// Pad the timestamps to maintain the same length. This is mainly for tabled
		// output where the padding is important for alignment.
		lenSrc := len(source)
		rpl := "timestamp"
		required := lenSrc - len(rpl) - 2

		return []byte("[" + fmt.Sprintf("%-*s", required, rpl) + "]")
	})

Copy link
Member Author

Choose a reason for hiding this comment

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

It then looks like this:

USERNAME   EMAIL                CREATED AT            STATUS   
testuser   testuser@coder.com   [timestamp         ]  active   
testuser2  testuser2@coder.com  [timestamp         ]  dormant  

Copy link
Member Author

Choose a reason for hiding this comment

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

And in json

    "created_at": "[timestamp                ]",
    "last_seen_at": "[timestamp                ]",

testuser2 testuser2@coder.com [timestamp] dormant
16 changes: 8 additions & 8 deletions cli/testdata/coder_users_list_--output_json.golden
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@
{
"id": "[first user ID]",
"username": "testuser",
"avatar_url": "",
"name": "",
"email": "testuser@coder.com",
"created_at": "[timestamp]",
"last_seen_at": "[timestamp]",
"status": "active",
"login_type": "password",
"theme_preference": "",
"organization_ids": [
"[first org ID]"
],
Expand All @@ -15,25 +18,22 @@
"name": "owner",
"display_name": "Owner"
}
],
"avatar_url": "",
"login_type": "password",
"theme_preference": ""
]
},
{
"id": "[second user ID]",
"username": "testuser2",
"avatar_url": "",
"name": "",
"email": "testuser2@coder.com",
"created_at": "[timestamp]",
"last_seen_at": "[timestamp]",
"status": "dormant",
"login_type": "password",
"theme_preference": "",
"organization_ids": [
"[first org ID]"
],
"roles": [],
"avatar_url": "",
"login_type": "password",
"theme_preference": ""
"roles": []
}
]
58 changes: 56 additions & 2 deletions coderd/apidoc/docs.go

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

50 changes: 48 additions & 2 deletions coderd/apidoc/swagger.json

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

18 changes: 11 additions & 7 deletions coderd/audit.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,13 +186,17 @@ func (api *API) convertAuditLog(ctx context.Context, dblog database.GetAuditLogs

if dblog.UserUsername.Valid {
user = &codersdk.User{
ID: dblog.UserID,
Username: dblog.UserUsername.String,
Email: dblog.UserEmail.String,
CreatedAt: dblog.UserCreatedAt.Time,
Status: codersdk.UserStatus(dblog.UserStatus.UserStatus),
Roles: []codersdk.Role{},
AvatarURL: dblog.UserAvatarUrl.String,
ReducedUser: codersdk.ReducedUser{
MinimalUser: codersdk.MinimalUser{
ID: dblog.UserID,
Username: dblog.UserUsername.String,
AvatarURL: dblog.UserAvatarUrl.String,
},
Email: dblog.UserEmail.String,
CreatedAt: dblog.UserCreatedAt.Time,
Status: codersdk.UserStatus(dblog.UserStatus.UserStatus),
},
Roles: []codersdk.Role{},
}

for _, roleName := range dblog.UserRoles {
Expand Down
Loading