Skip to content

Commit a5cd4cb

Browse files
authored
Merge branch 'main' into matifali/devcontainer
2 parents f15d298 + d843735 commit a5cd4cb

File tree

23 files changed

+277
-60
lines changed

23 files changed

+277
-60
lines changed

.github/actions/setup-tf/action.yaml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
name: "Setup Terraform"
2+
description: |
3+
Sets up Terraform for tests, builds, etc.
4+
runs:
5+
using: "composite"
6+
steps:
7+
- name: Install Terraform
8+
uses: hashicorp/setup-terraform@v2
9+
with:
10+
terraform_version: 1.5.2
11+
terraform_wrapper: false

.github/workflows/ci.yaml

Lines changed: 14 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,16 @@ jobs:
203203
go-version: 1.20.5
204204

205205
- name: Install prettier
206-
run: npm install -g prettier
206+
# We only need prettier for fmt, so do not install all dependencies.
207+
# There is no way to install a single package with yarn, so we have to
208+
# make a new package.json with only prettier listed as a dependency.
209+
# Then running `yarn` will only install prettier.
210+
run: |
211+
cd site
212+
mv package.json package.json.bak
213+
jq '{dependencies: {prettier: .devDependencies.prettier}}' < package.json.bak > package.json
214+
yarn --frozen-lockfile
215+
mv package.json.bak package.json
207216
208217
- name: Install shfmt
209218
run: go install mvdan.cc/sh/v3/cmd/shfmt@v3.5.0
@@ -231,11 +240,7 @@ jobs:
231240
- uses: actions/checkout@v3
232241

233242
- uses: ./.github/actions/setup-go
234-
235-
- uses: hashicorp/setup-terraform@v2
236-
with:
237-
terraform_version: 1.5.1
238-
terraform_wrapper: false
243+
- uses: ./.github/actions/setup-tf
239244

240245
- name: Test with Mock Database
241246
id: test
@@ -296,11 +301,7 @@ jobs:
296301
- uses: actions/checkout@v3
297302

298303
- uses: ./.github/actions/setup-go
299-
300-
- uses: hashicorp/setup-terraform@v2
301-
with:
302-
terraform_version: 1.5.1
303-
terraform_wrapper: false
304+
- uses: ./.github/actions/setup-tf
304305

305306
- name: Test with PostgreSQL Database
306307
run: |
@@ -340,11 +341,7 @@ jobs:
340341
- uses: actions/checkout@v3
341342

342343
- uses: ./.github/actions/setup-go
343-
344-
- uses: hashicorp/setup-terraform@v2
345-
with:
346-
terraform_version: 1.5.1
347-
terraform_wrapper: false
344+
- uses: ./.github/actions/setup-tf
348345

349346
- name: Run Tests
350347
run: |
@@ -479,11 +476,7 @@ jobs:
479476

480477
- uses: ./.github/actions/setup-node
481478
- uses: ./.github/actions/setup-go
482-
483-
- uses: hashicorp/setup-terraform@v2
484-
with:
485-
terraform_version: 1.5.1
486-
terraform_wrapper: false
479+
- uses: ./.github/actions/setup-tf
487480

488481
- name: Build
489482
run: |

.github/workflows/nightly-gauntlet.yaml

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,7 @@ jobs:
1919
- uses: actions/checkout@v3
2020

2121
- uses: ./.github/actions/setup-go
22-
23-
- uses: hashicorp/setup-terraform@v2
24-
with:
25-
terraform_version: 1.1.9
26-
terraform_wrapper: false
22+
- uses: ./.github/actions/setup-tf
2723

2824
- name: Run Tests
2925
run: |

cli/clitest/handlers.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package clitest
2+
3+
import (
4+
"testing"
5+
6+
"github.com/coder/coder/cli/clibase"
7+
)
8+
9+
// HandlersOK asserts that all commands have a handler.
10+
// Without a handler, the command has no default behavior. Even for
11+
// non-root commands (like 'groups' or 'users'), a handler is required.
12+
// These handlers are likely just the 'help' handler, but this must be
13+
// explicitly set.
14+
func HandlersOK(t *testing.T, cmd *clibase.Cmd) {
15+
cmd.Walk(func(cmd *clibase.Cmd) {
16+
if cmd.Handler == nil {
17+
// If you see this error, make the Handler a helper invoker.
18+
// Handler: func(inv *clibase.Invocation) error {
19+
// return inv.Command.HelpHandler(inv)
20+
// },
21+
t.Errorf("command %q has no handler, change to a helper invoker using: 'inv.Command.HelpHandler(inv)'", cmd.Name())
22+
}
23+
})
24+
}

cli/root.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,18 @@ func (r *RootCmd) Command(subcommands []*clibase.Cmd) (*clibase.Cmd, error) {
260260
// Add a wrapper to every command to enable debugging options.
261261
cmd.Walk(func(cmd *clibase.Cmd) {
262262
h := cmd.Handler
263+
if h == nil {
264+
// We should never have a nil handler, but if we do, do not
265+
// wrap it. Wrapping it just hides a nil pointer dereference.
266+
// If a nil handler exists, this is a developer bug. If no handler
267+
// is required for a command such as command grouping (e.g. `users'
268+
// and 'groups'), then the handler should be set to the helper
269+
// function.
270+
// func(inv *clibase.Invocation) error {
271+
// return inv.Command.HelpHandler(inv)
272+
// }
273+
return
274+
}
263275
cmd.Handler = func(i *clibase.Invocation) error {
264276
if !debugOptions {
265277
return h(i)

cli/root_test.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,3 +181,13 @@ func TestDERPHeaders(t *testing.T) {
181181

182182
require.Greater(t, atomic.LoadInt64(&derpCalled), int64(0), "expected /derp to be called at least once")
183183
}
184+
185+
func TestHandlersOK(t *testing.T) {
186+
t.Parallel()
187+
188+
var root cli.RootCmd
189+
cmd, err := root.Command(root.Core())
190+
require.NoError(t, err)
191+
192+
clitest.HandlersOK(t, cmd)
193+
}

coderd/apidoc/docs.go

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/apidoc/swagger.json

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

codersdk/templates.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,11 @@ type TemplateUser struct {
8585
}
8686

8787
type UpdateTemplateACL struct {
88-
UserPerms map[string]TemplateRole `json:"user_perms,omitempty"`
89-
GroupPerms map[string]TemplateRole `json:"group_perms,omitempty"`
88+
// UserPerms should be a mapping of user id to role. The user id must be the
89+
// uuid of the user, not a username or email address.
90+
UserPerms map[string]TemplateRole `json:"user_perms,omitempty" example:"<group_id>:admin,4df59e74-c027-470b-ab4d-cbba8963a5e9:use"`
91+
// GroupPerms should be a mapping of group id to role.
92+
GroupPerms map[string]TemplateRole `json:"group_perms,omitempty" example:"<user_id>>:admin,8bd26b20-f3e8-48be-a903-46bb920cf671:use"`
9093
}
9194

9295
type UpdateTemplateMeta struct {

docs/api/enterprise.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1080,12 +1080,12 @@ curl -X PATCH http://coder-server:8080/api/v2/templates/{template}/acl \
10801080
```json
10811081
{
10821082
"group_perms": {
1083-
"property1": "admin",
1084-
"property2": "admin"
1083+
"8bd26b20-f3e8-48be-a903-46bb920cf671": "use",
1084+
"<user_id>>": "admin"
10851085
},
10861086
"user_perms": {
1087-
"property1": "admin",
1088-
"property2": "admin"
1087+
"4df59e74-c027-470b-ab4d-cbba8963a5e9": "use",
1088+
"<group_id>": "admin"
10891089
}
10901090
}
10911091
```

docs/api/schemas.md

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4441,24 +4441,24 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in
44414441
```json
44424442
{
44434443
"group_perms": {
4444-
"property1": "admin",
4445-
"property2": "admin"
4444+
"8bd26b20-f3e8-48be-a903-46bb920cf671": "use",
4445+
"<user_id>>": "admin"
44464446
},
44474447
"user_perms": {
4448-
"property1": "admin",
4449-
"property2": "admin"
4448+
"4df59e74-c027-470b-ab4d-cbba8963a5e9": "use",
4449+
"<group_id>": "admin"
44504450
}
44514451
}
44524452
```
44534453

44544454
### Properties
44554455

4456-
| Name | Type | Required | Restrictions | Description |
4457-
| ------------------ | ---------------------------------------------- | -------- | ------------ | ----------- |
4458-
| `group_perms` | object | false | | |
4459-
| » `[any property]` | [codersdk.TemplateRole](#codersdktemplaterole) | false | | |
4460-
| `user_perms` | object | false | | |
4461-
| » `[any property]` | [codersdk.TemplateRole](#codersdktemplaterole) | false | | |
4456+
| Name | Type | Required | Restrictions | Description |
4457+
| ------------------ | ---------------------------------------------- | -------- | ------------ | ----------------------------------------------------------------------------------------------------------------------------- |
4458+
| `group_perms` | object | false | | Group perms should be a mapping of group ID to role. |
4459+
| » `[any property]` | [codersdk.TemplateRole](#codersdktemplaterole) | false | | |
4460+
| `user_perms` | object | false | | User perms should be a mapping of user ID to role. The user ID must be the uuid of the user, not a username or email address. |
4461+
| » `[any property]` | [codersdk.TemplateRole](#codersdktemplaterole) | false | | |
44624462

44634463
## codersdk.UpdateUserPasswordRequest
44644464

docs/manifest.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,11 @@
175175
"description": "Use docker inside containerized templates",
176176
"path": "./templates/docker-in-workspaces.md",
177177
"icon_path": "./images/icons/docker.svg"
178+
},
179+
{
180+
"title": "Terraform Modules",
181+
"description": "Reuse code across Coder templates",
182+
"path": "./templates/modules.md"
178183
}
179184
]
180185
},

docs/templates/modules.md

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
# Template inheritance
2+
3+
In instances where you want to reuse code across different Coder templates, such as common scripts or resource definitions, we suggest using [Terraform Modules](https://developer.hashicorp.com/terraform/language/modules).
4+
5+
These modules can be stored externally from Coder, like in a Git repository or a Terraform registry. Below is an example of how to reference a module in your template:
6+
7+
```hcl
8+
data "coder_workspace" "me" {}
9+
10+
module "coder-base" {
11+
source = "github.com/my-organization/coder-base"
12+
13+
# Modules take in variables and can provision infrastructure
14+
vpc_name = "devex-3"
15+
subnet_tags = { "name": data.coder_workspace.me.name }
16+
code_server_version = 4.14.1
17+
}
18+
19+
resource "coder_agent" "dev" {
20+
# Modules can provide outputs, such as helper scripts
21+
startup_script=<<EOF
22+
#!/bin/sh
23+
${module.coder-base.code_server_install_command}
24+
EOF
25+
}
26+
```
27+
28+
> Learn more about [creating modules](https://developer.hashicorp.com/terraform/language/modules) and [module sources](https://developer.hashicorp.com/terraform/language/modules/sources) in the Terraform documentation.
29+
30+
## Git authentication
31+
32+
If you are importing a module from a private git repository, the Coder server [or provisioner](../admin/provisioners.md) needs git credentials. Since this token will only be used for cloning your repositories with modules, it is best to create a token with limited access to repositories and no extra permissions. In GitHub, you can generate a [fine-grained token](https://docs.github.com/en/rest/overview/permissions-required-for-fine-grained-personal-access-tokens?apiVersion=2022-11-28) with read only access to repos.
33+
34+
If you are running Coder on a VM, make sure you have `git` installed and the `coder` user has access to the following files
35+
36+
```sh
37+
# /home/coder/.gitconfig
38+
[credential]
39+
helper = store
40+
```
41+
42+
```sh
43+
# /home/coder/.gitconfig
44+
45+
# GitHub example:
46+
https://your-github-username:your-github-pat@github.com
47+
```
48+
49+
If you are running Coder on Docker or Kubernetes, `git` is pre-installed in the Coder image. However, you still need to mount credentials. This can be done via a Docker volume mount or Kubernetes secrets.
50+
51+
### Passing git credentials in Kubernetes
52+
53+
First, create a `.gitconfig` and `.git-credentials` file on your local machine. You may want to do this in a temporary directory to avoid conflicting with your own git credentials.
54+
55+
Next, create the secret in Kubernetes. Be sure to do this in the same namespace that Coder is installed in.
56+
57+
```sh
58+
export NAMESPACE=coder
59+
kubectl apply -f - <<EOF
60+
apiVersion: v1
61+
kind: Secret
62+
metadata:
63+
name: git-secrets
64+
namespace: $NAMESPACE
65+
type: Opaque
66+
data:
67+
.gitconfig: $(cat .gitconfig | base64 | tr -d '\n')
68+
.git-credentials: $(cat .git-credentials | base64 | tr -d '\n')
69+
EOF
70+
```
71+
72+
Then, modify Coder's Helm values to mount the secret.
73+
74+
```yaml
75+
coder:
76+
volumes:
77+
- name: git-secrets
78+
secret:
79+
secretName: git-secrets
80+
volumeMounts:
81+
- name: git-secrets
82+
mountPath: "/home/coder/.gitconfig"
83+
subPath: .gitconfig
84+
readOnly: true
85+
- name: git-secrets
86+
mountPath: "/home/coder/.git-credentials"
87+
subPath: .git-credentials
88+
readOnly: true
89+
```

enterprise/cli/provisionerdaemons.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ func (r *RootCmd) provisionerDaemons() *clibase.Cmd {
2727
cmd := &clibase.Cmd{
2828
Use: "provisionerd",
2929
Short: "Manage provisioner daemons",
30+
Handler: func(inv *clibase.Invocation) error {
31+
return inv.Command.HelpHandler(inv)
32+
},
3033
Children: []*clibase.Cmd{
3134
r.provisionerDaemonStart(),
3235
},

enterprise/cli/root_test.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,13 @@ func newCLI(t *testing.T, args ...string) (*clibase.Invocation, config.Root) {
1717
require.NoError(t, err)
1818
return clitest.NewWithCommand(t, cmd, args...)
1919
}
20+
21+
func TestEnterpriseHandlersOK(t *testing.T) {
22+
t.Parallel()
23+
24+
var root cli.RootCmd
25+
cmd, err := root.Command(root.EnterpriseSubcommands())
26+
require.NoError(t, err)
27+
28+
clitest.HandlersOK(t, cmd)
29+
}

0 commit comments

Comments
 (0)