Skip to content

chore: update provisioner tag documentation with suggestions from #12315 #12347

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 4 commits into from
Feb 29, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
address PR comments
  • Loading branch information
johnstcn committed Feb 29, 2024
commit 4f774df7cf0aa52418fd681016f6e52241fad1d9
141 changes: 70 additions & 71 deletions coderd/provisionerdserver/acquirer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -338,30 +338,12 @@ func TestAcquirer_MatchTags(t *testing.T) {
acquireJobTags: map[string]string{"scope": "organization", "owner": ""},
expectAcquire: true,
},
{
name: "untagged provisioner and tagged job",
provisionerJobTags: map[string]string{"scope": "organization", "owner": "", "environment": "on-prem"},
acquireJobTags: map[string]string{"scope": "organization", "owner": ""},
expectAcquire: false,
},
{
name: "tagged provisioner and untagged job",
provisionerJobTags: map[string]string{"scope": "organization", "owner": ""},
acquireJobTags: map[string]string{"scope": "organization", "owner": "", "environment": "on-prem"},
expectAcquire: false,
},
{
name: "tagged provisioner and tagged job",
provisionerJobTags: map[string]string{"scope": "organization", "owner": "", "environment": "on-prem"},
acquireJobTags: map[string]string{"scope": "organization", "owner": "", "environment": "on-prem"},
expectAcquire: true,
},
{
name: "tagged provisioner and double-tagged job",
provisionerJobTags: map[string]string{"scope": "organization", "owner": "", "environment": "on-prem", "datacenter": "chicago"},
acquireJobTags: map[string]string{"scope": "organization", "owner": "", "environment": "on-prem"},
expectAcquire: false,
},
{
name: "double-tagged provisioner and tagged job",
provisionerJobTags: map[string]string{"scope": "organization", "owner": "", "environment": "on-prem"},
Expand All @@ -375,84 +357,107 @@ func TestAcquirer_MatchTags(t *testing.T) {
expectAcquire: true,
},
{
name: "owner-scoped provisioner and untagged job",
provisionerJobTags: map[string]string{"scope": "organization", "owner": ""},
acquireJobTags: map[string]string{"scope": "owner", "owner": "aaa"},
expectAcquire: false,
name: "user-scoped provisioner and user-scoped job",
provisionerJobTags: map[string]string{"scope": "user", "owner": "aaa"},
acquireJobTags: map[string]string{"scope": "user", "owner": "aaa"},
expectAcquire: true,
},
{
name: "owner-scoped provisioner and owner-scoped job",
provisionerJobTags: map[string]string{"scope": "owner", "owner": "aaa"},
acquireJobTags: map[string]string{"scope": "owner", "owner": "aaa"},
name: "user-scoped provisioner with tags and user-scoped job",
provisionerJobTags: map[string]string{"scope": "user", "owner": "aaa"},
acquireJobTags: map[string]string{"scope": "user", "owner": "aaa", "environment": "on-prem"},
expectAcquire: true,
},

{
name: "owner-scoped provisioner and different owner-scoped job",
provisionerJobTags: map[string]string{"scope": "owner", "owner": "bbb"},
acquireJobTags: map[string]string{"scope": "owner", "owner": "aaa"},
expectAcquire: false,
name: "user-scoped provisioner with tags and user-scoped job with tags",
provisionerJobTags: map[string]string{"scope": "user", "owner": "aaa", "environment": "on-prem"},
acquireJobTags: map[string]string{"scope": "user", "owner": "aaa", "environment": "on-prem"},
expectAcquire: true,
},
{
name: "user-scoped provisioner with multiple tags and user-scoped job with tags",
provisionerJobTags: map[string]string{"scope": "user", "owner": "aaa", "environment": "on-prem"},
acquireJobTags: map[string]string{"scope": "user", "owner": "aaa", "environment": "on-prem", "datacenter": "chicago"},
expectAcquire: true,
},
{
name: "user-scoped provisioner with multiple tags and user-scoped job with multiple tags",
provisionerJobTags: map[string]string{"scope": "user", "owner": "aaa", "environment": "on-prem", "datacenter": "chicago"},
acquireJobTags: map[string]string{"scope": "user", "owner": "aaa", "environment": "on-prem", "datacenter": "chicago"},
expectAcquire: true,
},
{
name: "org-scoped provisioner and owner-scoped job",
provisionerJobTags: map[string]string{"scope": "owner", "owner": "aaa"},
name: "untagged provisioner and tagged job",
provisionerJobTags: map[string]string{"scope": "organization", "owner": "", "environment": "on-prem"},
acquireJobTags: map[string]string{"scope": "organization", "owner": ""},
expectAcquire: false,
},
{
name: "owner-scoped provisioner and org-scoped job with tags",
provisionerJobTags: map[string]string{"scope": "owner", "owner": "aaa", "environment": "on-prem"},
acquireJobTags: map[string]string{"scope": "organization", "owner": ""},
name: "tagged provisioner and untagged job",
provisionerJobTags: map[string]string{"scope": "organization", "owner": ""},
acquireJobTags: map[string]string{"scope": "organization", "owner": "", "environment": "on-prem"},
expectAcquire: false,
},
{
name: "owner-scoped provisioner with tags and owner-scoped job",
provisionerJobTags: map[string]string{"scope": "owner", "owner": "aaa"},
acquireJobTags: map[string]string{"scope": "owner", "owner": "aaa", "environment": "on-prem"},
expectAcquire: true,
name: "tagged provisioner and double-tagged job",
provisionerJobTags: map[string]string{"scope": "organization", "owner": "", "environment": "on-prem", "datacenter": "chicago"},
acquireJobTags: map[string]string{"scope": "organization", "owner": "", "environment": "on-prem"},
expectAcquire: false,
},
{
name: "owner-scoped provisioner and owner-scoped job with tags",
provisionerJobTags: map[string]string{"scope": "owner", "owner": "aaa", "environment": "on-prem"},
acquireJobTags: map[string]string{"scope": "owner", "owner": "aaa"},
name: "double-tagged provisioner and double-tagged job with differing tags",
provisionerJobTags: map[string]string{"scope": "organization", "owner": "", "environment": "on-prem", "datacenter": "chicago"},
acquireJobTags: map[string]string{"scope": "organization", "owner": "", "environment": "on-prem", "datacenter": "new_york"},
expectAcquire: false,
},
{
name: "owner-scoped provisioner with tags and owner-scoped job with tags",
provisionerJobTags: map[string]string{"scope": "owner", "owner": "aaa", "environment": "on-prem"},
acquireJobTags: map[string]string{"scope": "owner", "owner": "aaa", "environment": "on-prem"},
expectAcquire: true,
name: "user-scoped provisioner and untagged job",
provisionerJobTags: map[string]string{"scope": "organization", "owner": ""},
acquireJobTags: map[string]string{"scope": "user", "owner": "aaa"},
expectAcquire: false,
},
{
name: "owner-scoped provisioner with multiple tags and owner-scoped job with tags",
provisionerJobTags: map[string]string{"scope": "owner", "owner": "aaa", "environment": "on-prem"},
acquireJobTags: map[string]string{"scope": "owner", "owner": "aaa", "environment": "on-prem", "datacenter": "chicago"},
expectAcquire: true,
name: "user-scoped provisioner and different user-scoped job",
provisionerJobTags: map[string]string{"scope": "user", "owner": "bbb"},
acquireJobTags: map[string]string{"scope": "user", "owner": "aaa"},
expectAcquire: false,
},
{
name: "owner-scoped provisioner with tags and owner-scoped job with multiple tags",
provisionerJobTags: map[string]string{"scope": "owner", "owner": "aaa", "environment": "on-prem", "datacenter": "chicago"},
acquireJobTags: map[string]string{"scope": "owner", "owner": "aaa", "environment": "on-prem"},
name: "org-scoped provisioner and user-scoped job",
provisionerJobTags: map[string]string{"scope": "user", "owner": "aaa"},
acquireJobTags: map[string]string{"scope": "organization", "owner": ""},
expectAcquire: false,
},
{
name: "owner-scoped provisioner with tags and owner-scoped job with multiple tags",
provisionerJobTags: map[string]string{"scope": "owner", "owner": "aaa", "environment": "on-prem", "datacenter": "chicago"},
acquireJobTags: map[string]string{"scope": "owner", "owner": "aaa", "environment": "on-prem", "datacenter": "chicago"},
expectAcquire: true,
name: "user-scoped provisioner and org-scoped job with tags",
provisionerJobTags: map[string]string{"scope": "user", "owner": "aaa", "environment": "on-prem"},
acquireJobTags: map[string]string{"scope": "organization", "owner": ""},
expectAcquire: false,
},
{
name: "owner-scoped provisioner with tags and owner-scoped job with differing tags",
provisionerJobTags: map[string]string{"scope": "owner", "owner": "aaa", "environment": "on-prem", "datacenter": "new_york"},
acquireJobTags: map[string]string{"scope": "owner", "owner": "aaa", "environment": "on-prem", "datacenter": "chicago"},
name: "user-scoped provisioner and user-scoped job with tags",
provisionerJobTags: map[string]string{"scope": "user", "owner": "aaa", "environment": "on-prem"},
acquireJobTags: map[string]string{"scope": "user", "owner": "aaa"},
expectAcquire: false,
},
{
name: "user-scoped provisioner with tags and user-scoped job with multiple tags",
provisionerJobTags: map[string]string{"scope": "user", "owner": "aaa", "environment": "on-prem", "datacenter": "chicago"},
acquireJobTags: map[string]string{"scope": "user", "owner": "aaa", "environment": "on-prem"},
expectAcquire: false,
},
{
name: "user-scoped provisioner with tags and user-scoped job with differing tags",
provisionerJobTags: map[string]string{"scope": "user", "owner": "aaa", "environment": "on-prem", "datacenter": "new_york"},
acquireJobTags: map[string]string{"scope": "user", "owner": "aaa", "environment": "on-prem", "datacenter": "chicago"},
expectAcquire: false,
},
}
for _, tt := range testCases {
tt := tt
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
ctx := testutil.Context(t, testutil.WaitShort/2)
ctx := testutil.Context(t, testutil.WaitShort)
// NOTE: explicitly not using fake store for this test.
db, ps := dbtestutil.NewDB(t)
log := slogtest.Make(t, nil).Leveled(slog.LevelDebug)
Expand Down Expand Up @@ -503,17 +508,11 @@ func TestAcquirer_MatchTags(t *testing.T) {
// turn the JSON map into k=v for readability
kvs := func(m map[string]string) string {
ss := make([]string, 0, len(m))
// always start with scope and owner
ss = append(ss, "scope"+"="+m["scope"])
ss = append(ss, "owner"+"="+m["owner"])
for k, v := range m {
if k == "scope" || k == "owner" {
continue
}
if len(v) == 0 {
v = `""`
// ensure consistent ordering of tags
for _, k := range []string{"scope", "owner", "environment", "datacenter"} {
if v, found := m[k]; found {
ss = append(ss, k+"="+v)
}
ss = append(ss, k+"="+v)
}
return strings.Join(ss, " ")
}
Expand Down
73 changes: 47 additions & 26 deletions docs/admin/provisioners.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,20 @@ the [Helm example](#example-running-an-external-provisioner-with-helm) below.

## Types of provisioners

Provisioners can broadly be categorized by scope: `organization` or `user`.
Provisioners can broadly be categorized by scope: `organization` or `user`. The
scope of a provisioner can be specified with
[`-tag=scope=<scope>`](../cli/provisionerd_start.md#t---tag) when starting the
provisioner daemon. Only users with at least the
[Template Admin](../admin/users.md#roles) role or higher may create
organization-scoped provisioner daemons.

There are two exceptions:

- [Built-in provisioners](../cli/server.md#provisioner-daemons) are always
organization-scoped.
- External provisioners started using a
[pre-shared key (PSK)](../cli/provisionerd_start.md#psk) are always
organization-scoped.

### Organization-Scoped Provisioners

Expand All @@ -62,8 +75,8 @@ coder provisionerd start

**User-scoped Provisioners** can only pick up build jobs created from
user-tagged templates. Unlike the other provisioner types, any Coder user can
run user provisioners, but they have no impact unless there is at least one
other template with the `scope=user` provisioner tag.
run user provisioners, but they have no impact unless there exists at least one
template with the `scope=user` provisioner tag.

```shell
coder provisionerd start \
Expand All @@ -86,7 +99,7 @@ automatically.
- Organization-scoped provisioners always have the implicit tags
`scope=organization owner=""`
- User-scoped provisioners always have the implicit tags
`scope=owner owner=<uuid>`
`scope=user owner=<uuid>`

For example:

Expand Down Expand Up @@ -125,31 +138,39 @@ The external provisioner in the above example can run build jobs with tags:

However, it will not pick up any build jobs that do not have either of the
`environment` or `datacenter` tags set. It will also not pick up any build jobs
from templates with the `user` tag set.
from templates with the tag `scope=user` set.

This is illustrated in the below table:

| Provisioner Tags | Job Tags | Can Run Job? |
| ---------------------------------------------------------------- | ---------------------------------------------------------------- | ------------ |
| scope=organization owner= | scope=organization owner= | ✅ |
| scope=organization owner= | scope=organization owner= environment=on-prem | ❌ |
| scope=organization owner= environment=on-prem | scope=organization owner= | ❌ |
| scope=organization owner= environment=on-prem | scope=organization owner= environment=on-prem | ✅ |
| scope=organization owner= environment=on-prem | scope=organization owner= environment=on-prem datacenter=chicago | ❌ |
| scope=organization owner= environment=on-prem datacenter=chicago | scope=organization owner= environment=on-prem | ✅ |
| scope=organization owner= environment=on-prem datacenter=chicago | scope=organization owner= environment=on-prem datacenter=chicago | ✅ |
| scope=owner owner=aaa | scope=organization owner= | ❌ |
| scope=owner owner=aaa | scope=owner owner=aaa | ✅ |
| scope=owner owner=aaa | scope=owner owner=bbb | ❌ |
| scope=organization owner= | scope=owner owner=aaa | ❌ |
| scope=organization owner= | scope=owner owner=aaa environment=on-prem | ❌ |
| scope=owner owner=aaa environment=on-prem | scope=owner owner=aaa | ✅ |
| scope=owner owner=aaa | scope=owner owner=aaa environment=on-prem | ❌ |
| scope=owner owner=aaa environment=on-prem | scope=owner owner=aaa environment=on-prem | ✅ |
| scope=owner owner=aaa environment=on-prem datacenter=chicago | scope=owner owner=aaa environment=on-prem | ✅ |
| scope=owner owner=aaa environment=on-prem | scope=owner owner=aaa environment=on-prem datacenter=chicago | ❌ |
| scope=owner owner=aaa environment=on-prem datacenter=chicago | scope=owner owner=aaa environment=on-prem datacenter=chicago | ✅ |
| scope=owner owner=aaa environment=on-prem datacenter=chicago | scope=owner owner=aaa environment=on-prem datacenter=new_york | ❌ |
| Provisioner Tags | Job Tags | Can Run Job? |
| ----------------------------------------------------------------- | ---------------------------------------------------------------- | ------------ |
| scope=organization owner= | scope=organization owner= | ✅ |
| scope=organization owner= environment=on-prem | scope=organization owner= environment=on-prem | ✅ |
| scope=organization owner= environment=on-prem datacenter=chicago | scope=organization owner= environment=on-prem | ✅ |
| scope=organization owner= environment=on-prem datacenter=chicago | scope=organization owner= environment=on-prem datacenter=chicago | ✅ |
| scope=user owner=aaa | scope=user owner=aaa | ✅ |
| scope=user owner=aaa environment=on-prem | scope=user owner=aaa | ✅ |
| scope=user owner=aaa environment=on-prem | scope=user owner=aaa environment=on-prem | ✅ |
| scope=user owner=aaa environment=on-prem datacenter=chicago | scope=user owner=aaa environment=on-prem | ✅ |
| scope=user owner=aaa environment=on-prem datacenter=chicago | scope=user owner=aaa environment=on-prem datacenter=chicago | ✅ |
| scope=organization owner= | scope=organization owner= environment=on-prem | ❌ |
| scope=organization owner= environment=on-prem | scope=organization owner= | ❌ |
| scope=organization owner= environment=on-prem | scope=organization owner= environment=on-prem datacenter=chicago | ❌ |
| scope=organization owner= environment=on-prem datacenter=new_york | scope=organization owner= environment=on-prem datacenter=chicago | ❌ |
| scope=user owner=aaa | scope=organization owner= | ❌ |
| scope=user owner=aaa | scope=user owner=bbb | ❌ |
| scope=organization owner= | scope=user owner=aaa | ❌ |
| scope=organization owner= | scope=user owner=aaa environment=on-prem | ❌ |
| scope=user owner=aaa | scope=user owner=aaa environment=on-prem | ❌ |
| scope=user owner=aaa environment=on-prem | scope=user owner=aaa environment=on-prem datacenter=chicago | ❌ |
| scope=user owner=aaa environment=on-prem datacenter=chicago | scope=user owner=aaa environment=on-prem datacenter=new_york | ❌ |

> **Note to maintainers:** to generate this table, run the following command and
> copy the output:
>
> ```
> go test -v -count=1 ./coderd/provisionerdserver/ -test.run='^TestAcquirer_MatchTags/GenTable$'
> ```

## Example: Running an external provisioner with Helm

Expand Down