Skip to content

Commit 1fc56bb

Browse files
committed
compat
1 parent 28bab5a commit 1fc56bb

File tree

3 files changed

+121
-53
lines changed

3 files changed

+121
-53
lines changed

docs/data-sources/user.md

+1
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,6 @@ Use this data source to fetch information about a user.
2222
- `groups` (List of String) The groups of which the user is a member.
2323
- `id` (String) The UUID of the user.
2424
- `name` (String) The username of the user.
25+
- `session_token` (String) Session token for authenticating with a Coder deployment. It is regenerated every time a workspace is started.
2526
- `ssh_private_key` (String, Sensitive) The user's generated SSH private key.
2627
- `ssh_public_key` (String) The user's generated SSH public key.

provider/user.go

+48-22
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"os"
77
"strings"
88

9+
"github.com/google/uuid"
910
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
1011
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
1112
)
@@ -20,50 +21,70 @@ func userDataSource() *schema.Resource {
2021
Description: "Use this data source to fetch information about a user.",
2122
ReadContext: func(ctx context.Context, rd *schema.ResourceData, i interface{}) diag.Diagnostics {
2223
if idStr, ok := os.LookupEnv("CODER_USER_ID"); !ok {
23-
return diag.Errorf("missing user id")
24+
rd.SetId(uuid.NewString())
2425
} else {
2526
rd.SetId(idStr)
2627
}
2728

28-
if username, ok := os.LookupEnv("CODER_USER_NAME"); !ok {
29-
return diag.Errorf("missing user username")
30-
} else {
29+
if username, ok := os.LookupEnv("CODER_USER_NAME"); ok {
3130
_ = rd.Set("name", username)
31+
} else if altUsername, ok := os.LookupEnv("CODER_WORKSPACE_OWNER"); ok {
32+
_ = rd.Set("name", altUsername)
33+
} else {
34+
return diag.Errorf("missing user name")
3235
}
3336

34-
if fullname, ok := os.LookupEnv("CODER_USER_FULL_NAME"); !ok {
35-
_ = rd.Set("name", "default") // compat
36-
} else {
37+
if fullname, ok := os.LookupEnv("CODER_USER_FULL_NAME"); ok {
3738
_ = rd.Set("full_name", fullname)
39+
} else if altFullname, ok := os.LookupEnv("CODER_WORKSPACE_OWNER_NAME"); ok {
40+
// Compatibility: read from CODER_WORKSPACE_OWNER_NAME
41+
_ = rd.Set("full_name", altFullname)
42+
} else { // fallback
43+
return diag.Errorf("missing user full_name")
3844
}
3945

40-
if email, ok := os.LookupEnv("CODER_USER_EMAIL"); !ok {
41-
return diag.Errorf("missing user email")
42-
} else {
46+
if email, ok := os.LookupEnv("CODER_USER_EMAIL"); ok {
4347
_ = rd.Set("email", email)
48+
} else if altEmail, ok := os.LookupEnv("CODER_WORKSPACE_OWNER_EMAIL"); ok {
49+
_ = rd.Set("email", altEmail)
50+
} else {
51+
return diag.Errorf("missing user email")
4452
}
4553

46-
if sshPubKey, ok := os.LookupEnv("CODER_USER_SSH_PUBLIC_KEY"); !ok {
47-
return diag.Errorf("missing user ssh_public_key")
48-
} else {
54+
if sshPubKey, ok := os.LookupEnv("CODER_USER_SSH_PUBLIC_KEY"); ok {
4955
_ = rd.Set("ssh_public_key", sshPubKey)
56+
} else {
57+
// Compat: do not error
58+
_ = rd.Set("ssh_public_key", "missing")
5059
}
5160

52-
if sshPrivKey, ok := os.LookupEnv("CODER_USER_SSH_PRIVATE_KEY"); !ok {
53-
return diag.Errorf("missing user ssh_private_key")
54-
} else {
61+
if sshPrivKey, ok := os.LookupEnv("CODER_USER_SSH_PRIVATE_KEY"); ok {
5562
_ = rd.Set("ssh_private_key", sshPrivKey)
63+
} else {
64+
// Compat: do not error
65+
_ = rd.Set("ssh_private_key", "missing")
5666
}
5767

58-
groupsRaw, ok := os.LookupEnv("CODER_USER_GROUPS")
59-
if !ok {
68+
var groups []string
69+
if groupsRaw, ok := os.LookupEnv("CODER_USER_GROUPS"); ok {
70+
if err := json.NewDecoder(strings.NewReader(groupsRaw)).Decode(&groups); err != nil {
71+
return diag.Errorf("invalid user groups: %s", err.Error())
72+
}
73+
} else if altGroupsRaw, ok := os.LookupEnv("CODER_WORKSPACE_OWNER_GROUPS"); ok {
74+
if err := json.NewDecoder(strings.NewReader(altGroupsRaw)).Decode(&groups); err != nil {
75+
return diag.Errorf("invalid workspace owner groups: %s", err.Error())
76+
}
77+
} else {
6078
return diag.Errorf("missing user groups")
6179
}
62-
var groups []string
63-
if err := json.NewDecoder(strings.NewReader(groupsRaw)).Decode(&groups); err != nil {
64-
return diag.Errorf("invalid user groups: %s", err.Error())
80+
_ = rd.Set("groups", groups)
81+
82+
if tok, ok := os.LookupEnv("CODER_USER_SESSION_TOKEN"); ok {
83+
_ = rd.Set("session_token", tok)
84+
} else if altTok, ok := os.LookupEnv("CODER_WORKSPACE_OWNER_SESSION_TOKEN"); ok {
85+
_ = rd.Set("session_token", altTok)
6586
} else {
66-
_ = rd.Set("groups", groups)
87+
return diag.Errorf("missing user session_token")
6788
}
6889

6990
return nil
@@ -108,6 +129,11 @@ func userDataSource() *schema.Resource {
108129
Computed: true,
109130
Description: "The groups of which the user is a member.",
110131
},
132+
"session_token": {
133+
Type: schema.TypeString,
134+
Computed: true,
135+
Description: "Session token for authenticating with a Coder deployment. It is regenerated every time a workspace is started.",
136+
},
111137
},
112138
}
113139
}

provider/user_test.go

+72-31
Original file line numberDiff line numberDiff line change
@@ -24,42 +24,83 @@ const (
2424
)
2525

2626
func TestUserDatasource(t *testing.T) {
27-
t.Setenv("CODER_USER_ID", "11111111-1111-1111-1111-111111111111")
28-
t.Setenv("CODER_USER_NAME", "owner123")
29-
t.Setenv("CODER_USER_AVATAR_URL", "https://example.com/avatar.png")
30-
t.Setenv("CODER_USER_FULL_NAME", "Mr Owner")
31-
t.Setenv("CODER_USER_EMAIL", "[email protected]")
32-
t.Setenv("CODER_USER_SSH_PUBLIC_KEY", testSSHEd25519PublicKey)
33-
t.Setenv("CODER_USER_SSH_PRIVATE_KEY", testSSHEd25519PrivateKey)
34-
t.Setenv("CODER_USER_GROUPS", `["group1", "group2"]`)
27+
t.Run("OK", func(t *testing.T) {
28+
t.Setenv("CODER_USER_ID", "11111111-1111-1111-1111-111111111111")
29+
t.Setenv("CODER_USER_NAME", "owner123")
30+
t.Setenv("CODER_USER_FULL_NAME", "Mr Owner")
31+
t.Setenv("CODER_USER_EMAIL", "[email protected]")
32+
t.Setenv("CODER_USER_SSH_PUBLIC_KEY", testSSHEd25519PublicKey)
33+
t.Setenv("CODER_USER_SSH_PRIVATE_KEY", testSSHEd25519PrivateKey)
34+
t.Setenv("CODER_USER_GROUPS", `["group1", "group2"]`)
35+
t.Setenv("CODER_USER_SESSION_TOKEN", `supersecret`)
3536

36-
resource.Test(t, resource.TestCase{
37-
Providers: map[string]*schema.Provider{
38-
"coder": provider.New(),
39-
},
40-
IsUnitTest: true,
41-
Steps: []resource.TestStep{{
42-
Config: `
37+
resource.Test(t, resource.TestCase{
38+
Providers: map[string]*schema.Provider{
39+
"coder": provider.New(),
40+
},
41+
IsUnitTest: true,
42+
Steps: []resource.TestStep{{
43+
Config: `
4344
provider "coder" {}
4445
data "coder_user" "me" {}
4546
`,
46-
Check: func(s *terraform.State) error {
47-
require.Len(t, s.Modules, 1)
48-
require.Len(t, s.Modules[0].Resources, 1)
49-
resource := s.Modules[0].Resources["data.coder_user.me"]
50-
require.NotNil(t, resource)
47+
Check: func(s *terraform.State) error {
48+
require.Len(t, s.Modules, 1)
49+
require.Len(t, s.Modules[0].Resources, 1)
50+
resource := s.Modules[0].Resources["data.coder_user.me"]
51+
require.NotNil(t, resource)
52+
53+
attrs := resource.Primary.Attributes
54+
assert.Equal(t, "11111111-1111-1111-1111-111111111111", attrs["id"])
55+
assert.Equal(t, "owner123", attrs["name"])
56+
assert.Equal(t, "Mr Owner", attrs["full_name"])
57+
assert.Equal(t, "[email protected]", attrs["email"])
58+
assert.Equal(t, testSSHEd25519PublicKey, attrs["ssh_public_key"])
59+
assert.Equal(t, testSSHEd25519PrivateKey, attrs["ssh_private_key"])
60+
assert.Equal(t, `group1`, attrs["groups.0"])
61+
assert.Equal(t, `group2`, attrs["groups.1"])
62+
assert.Equal(t, `supersecret`, attrs["session_token"])
63+
return nil
64+
},
65+
}},
66+
})
67+
})
68+
69+
t.Run("Compat", func(t *testing.T) {
70+
t.Setenv("CODER_WORKSPACE_OWNER", "owner123")
71+
t.Setenv("CODER_WORKSPACE_OWNER_NAME", "Mr Owner")
72+
t.Setenv("CODER_WORKSPACE_OWNER_EMAIL", "[email protected]")
73+
t.Setenv("CODER_WORKSPACE_OWNER_GROUPS", `["group1", "group2"]`)
74+
t.Setenv("CODER_WORKSPACE_OWNER_SESSION_TOKEN", `supersecret`)
5175

52-
attrs := resource.Primary.Attributes
53-
assert.Equal(t, "11111111-1111-1111-1111-111111111111", attrs["id"])
54-
assert.Equal(t, "owner123", attrs["name"])
55-
assert.Equal(t, "Mr Owner", attrs["full_name"])
56-
assert.Equal(t, "[email protected]", attrs["email"])
57-
assert.Equal(t, testSSHEd25519PublicKey, attrs["ssh_public_key"])
58-
assert.Equal(t, testSSHEd25519PrivateKey, attrs["ssh_private_key"])
59-
assert.Equal(t, `group1`, attrs["groups.0"])
60-
assert.Equal(t, `group2`, attrs["groups.1"])
61-
return nil
76+
resource.Test(t, resource.TestCase{
77+
Providers: map[string]*schema.Provider{
78+
"coder": provider.New(),
6279
},
63-
}},
80+
IsUnitTest: true,
81+
Steps: []resource.TestStep{{
82+
Config: `
83+
provider "coder" {}
84+
data "coder_user" "me" {}
85+
`,
86+
Check: func(s *terraform.State) error {
87+
require.Len(t, s.Modules, 1)
88+
require.Len(t, s.Modules[0].Resources, 1)
89+
resource := s.Modules[0].Resources["data.coder_user.me"]
90+
require.NotNil(t, resource)
91+
92+
attrs := resource.Primary.Attributes
93+
assert.NotEmpty(t, attrs["id"])
94+
assert.Equal(t, "owner123", attrs["name"])
95+
assert.Equal(t, "Mr Owner", attrs["full_name"])
96+
assert.Equal(t, "[email protected]", attrs["email"])
97+
assert.Equal(t, "missing", attrs["ssh_public_key"])
98+
assert.Equal(t, "missing", attrs["ssh_private_key"])
99+
assert.Equal(t, `group1`, attrs["groups.0"])
100+
assert.Equal(t, `group2`, attrs["groups.1"])
101+
return nil
102+
},
103+
}},
104+
})
64105
})
65106
}

0 commit comments

Comments
 (0)