diff --git a/coderd/apidoc/docs.go b/coderd/apidoc/docs.go index 01579c0c659a2..487aac8f7fb76 100644 --- a/coderd/apidoc/docs.go +++ b/coderd/apidoc/docs.go @@ -11024,6 +11024,12 @@ const docTemplate = `{ "organization": { "type": "string", "format": "uuid" + }, + "tags": { + "type": "object", + "additionalProperties": { + "type": "string" + } } } }, diff --git a/coderd/apidoc/swagger.json b/coderd/apidoc/swagger.json index a9b61c05f18e4..be72fcb8d03ac 100644 --- a/coderd/apidoc/swagger.json +++ b/coderd/apidoc/swagger.json @@ -9950,6 +9950,12 @@ "organization": { "type": "string", "format": "uuid" + }, + "tags": { + "type": "object", + "additionalProperties": { + "type": "string" + } } } }, diff --git a/coderd/database/dbgen/dbgen.go b/coderd/database/dbgen/dbgen.go index 29f7b1f2e5a69..43cda96778841 100644 --- a/coderd/database/dbgen/dbgen.go +++ b/coderd/database/dbgen/dbgen.go @@ -472,6 +472,7 @@ func ProvisionerKey(t testing.TB, db database.Store, orig database.ProvisionerKe OrganizationID: takeFirst(orig.OrganizationID, uuid.New()), Name: takeFirst(orig.Name, namesgenerator.GetRandomName(1)), HashedSecret: orig.HashedSecret, + Tags: orig.Tags, }) require.NoError(t, err, "insert provisioner key") return key diff --git a/coderd/database/dbmem/dbmem.go b/coderd/database/dbmem/dbmem.go index f74197e234fa8..827d99a2c14df 100644 --- a/coderd/database/dbmem/dbmem.go +++ b/coderd/database/dbmem/dbmem.go @@ -6586,6 +6586,7 @@ func (q *FakeQuerier) InsertProvisionerKey(_ context.Context, arg database.Inser OrganizationID: arg.OrganizationID, Name: strings.ToLower(arg.Name), HashedSecret: arg.HashedSecret, + Tags: arg.Tags, } q.provisionerKeys = append(q.provisionerKeys, provisionerKey) @@ -7276,13 +7277,7 @@ func (q *FakeQuerier) ListProvisionerKeysByOrganization(_ context.Context, organ keys := make([]database.ProvisionerKey, 0) for _, key := range q.provisionerKeys { if key.OrganizationID == organizationID { - keys = append(keys, database.ProvisionerKey{ - ID: key.ID, - CreatedAt: key.CreatedAt, - OrganizationID: key.OrganizationID, - Name: key.Name, - HashedSecret: key.HashedSecret, - }) + keys = append(keys, key) } } diff --git a/coderd/database/dump.sql b/coderd/database/dump.sql index d07519cff7de0..dc15cf9bd4af8 100644 --- a/coderd/database/dump.sql +++ b/coderd/database/dump.sql @@ -754,7 +754,8 @@ CREATE TABLE provisioner_keys ( created_at timestamp with time zone NOT NULL, organization_id uuid NOT NULL, name character varying(64) NOT NULL, - hashed_secret bytea NOT NULL + hashed_secret bytea NOT NULL, + tags jsonb NOT NULL ); CREATE TABLE replicas ( diff --git a/coderd/database/migrations/000231_provisioner_key_tags.down.sql b/coderd/database/migrations/000231_provisioner_key_tags.down.sql new file mode 100644 index 0000000000000..11ea29e62ec44 --- /dev/null +++ b/coderd/database/migrations/000231_provisioner_key_tags.down.sql @@ -0,0 +1 @@ +ALTER TABLE provisioner_keys DROP COLUMN tags; diff --git a/coderd/database/migrations/000231_provisioner_key_tags.up.sql b/coderd/database/migrations/000231_provisioner_key_tags.up.sql new file mode 100644 index 0000000000000..34a1d768cb285 --- /dev/null +++ b/coderd/database/migrations/000231_provisioner_key_tags.up.sql @@ -0,0 +1,2 @@ +ALTER TABLE provisioner_keys ADD COLUMN tags jsonb DEFAULT '{}'::jsonb NOT NULL; +ALTER TABLE provisioner_keys ALTER COLUMN tags DROP DEFAULT; diff --git a/coderd/database/models.go b/coderd/database/models.go index 9b35e1c0f79b3..0ee78e286516e 100644 --- a/coderd/database/models.go +++ b/coderd/database/models.go @@ -2191,6 +2191,7 @@ type ProvisionerKey struct { OrganizationID uuid.UUID `db:"organization_id" json:"organization_id"` Name string `db:"name" json:"name"` HashedSecret []byte `db:"hashed_secret" json:"hashed_secret"` + Tags StringMap `db:"tags" json:"tags"` } type Replica struct { diff --git a/coderd/database/queries.sql.go b/coderd/database/queries.sql.go index b761e451b3041..f383f2e7c0d5d 100644 --- a/coderd/database/queries.sql.go +++ b/coderd/database/queries.sql.go @@ -5533,7 +5533,7 @@ func (q *sqlQuerier) DeleteProvisionerKey(ctx context.Context, id uuid.UUID) err const getProvisionerKeyByID = `-- name: GetProvisionerKeyByID :one SELECT - id, created_at, organization_id, name, hashed_secret + id, created_at, organization_id, name, hashed_secret, tags FROM provisioner_keys WHERE @@ -5549,13 +5549,14 @@ func (q *sqlQuerier) GetProvisionerKeyByID(ctx context.Context, id uuid.UUID) (P &i.OrganizationID, &i.Name, &i.HashedSecret, + &i.Tags, ) return i, err } const getProvisionerKeyByName = `-- name: GetProvisionerKeyByName :one SELECT - id, created_at, organization_id, name, hashed_secret + id, created_at, organization_id, name, hashed_secret, tags FROM provisioner_keys WHERE @@ -5578,21 +5579,23 @@ func (q *sqlQuerier) GetProvisionerKeyByName(ctx context.Context, arg GetProvisi &i.OrganizationID, &i.Name, &i.HashedSecret, + &i.Tags, ) return i, err } const insertProvisionerKey = `-- name: InsertProvisionerKey :one INSERT INTO - provisioner_keys ( - id, + provisioner_keys ( + id, created_at, organization_id, - name, - hashed_secret - ) + name, + hashed_secret, + tags + ) VALUES - ($1, $2, $3, lower($5), $4) RETURNING id, created_at, organization_id, name, hashed_secret + ($1, $2, $3, lower($6), $4, $5) RETURNING id, created_at, organization_id, name, hashed_secret, tags ` type InsertProvisionerKeyParams struct { @@ -5600,6 +5603,7 @@ type InsertProvisionerKeyParams struct { CreatedAt time.Time `db:"created_at" json:"created_at"` OrganizationID uuid.UUID `db:"organization_id" json:"organization_id"` HashedSecret []byte `db:"hashed_secret" json:"hashed_secret"` + Tags StringMap `db:"tags" json:"tags"` Name string `db:"name" json:"name"` } @@ -5609,6 +5613,7 @@ func (q *sqlQuerier) InsertProvisionerKey(ctx context.Context, arg InsertProvisi arg.CreatedAt, arg.OrganizationID, arg.HashedSecret, + arg.Tags, arg.Name, ) var i ProvisionerKey @@ -5618,13 +5623,14 @@ func (q *sqlQuerier) InsertProvisionerKey(ctx context.Context, arg InsertProvisi &i.OrganizationID, &i.Name, &i.HashedSecret, + &i.Tags, ) return i, err } const listProvisionerKeysByOrganization = `-- name: ListProvisionerKeysByOrganization :many SELECT - id, created_at, organization_id, name, hashed_secret + id, created_at, organization_id, name, hashed_secret, tags FROM provisioner_keys WHERE @@ -5646,6 +5652,7 @@ func (q *sqlQuerier) ListProvisionerKeysByOrganization(ctx context.Context, orga &i.OrganizationID, &i.Name, &i.HashedSecret, + &i.Tags, ); err != nil { return nil, err } diff --git a/coderd/database/queries/provisionerkeys.sql b/coderd/database/queries/provisionerkeys.sql index 22e714eca350d..ac41eb2d444d2 100644 --- a/coderd/database/queries/provisionerkeys.sql +++ b/coderd/database/queries/provisionerkeys.sql @@ -1,14 +1,15 @@ -- name: InsertProvisionerKey :one INSERT INTO - provisioner_keys ( - id, + provisioner_keys ( + id, created_at, organization_id, - name, - hashed_secret - ) + name, + hashed_secret, + tags + ) VALUES - ($1, $2, $3, lower(@name), $4) RETURNING *; + ($1, $2, $3, lower(@name), $4, $5) RETURNING *; -- name: GetProvisionerKeyByID :one SELECT diff --git a/coderd/database/sqlc.yaml b/coderd/database/sqlc.yaml index fc56cf943dc3b..2896e7035fcfa 100644 --- a/coderd/database/sqlc.yaml +++ b/coderd/database/sqlc.yaml @@ -44,6 +44,9 @@ sql: - column: "provisioner_daemons.tags" go_type: type: "StringMap" + - column: "provisioner_keys.tags" + go_type: + type: "StringMap" - column: "provisioner_jobs.tags" go_type: type: "StringMap" diff --git a/coderd/provisionerkey/provisionerkey.go b/coderd/provisionerkey/provisionerkey.go index 70354c140b73e..5be3658f6a5be 100644 --- a/coderd/provisionerkey/provisionerkey.go +++ b/coderd/provisionerkey/provisionerkey.go @@ -14,7 +14,7 @@ import ( "github.com/coder/coder/v2/cryptorand" ) -func New(organizationID uuid.UUID, name string) (database.InsertProvisionerKeyParams, string, error) { +func New(organizationID uuid.UUID, name string, tags map[string]string) (database.InsertProvisionerKeyParams, string, error) { id := uuid.New() secret, err := cryptorand.HexString(64) if err != nil { @@ -23,12 +23,17 @@ func New(organizationID uuid.UUID, name string) (database.InsertProvisionerKeyPa hashedSecret := HashSecret(secret) token := fmt.Sprintf("%s:%s", id, secret) + if tags == nil { + tags = map[string]string{} + } + return database.InsertProvisionerKeyParams{ ID: id, CreatedAt: dbtime.Now(), OrganizationID: organizationID, Name: name, HashedSecret: hashedSecret, + Tags: tags, }, token, nil } diff --git a/codersdk/provisionerdaemons.go b/codersdk/provisionerdaemons.go index e8be78525d6e6..df481dc04a18d 100644 --- a/codersdk/provisionerdaemons.go +++ b/codersdk/provisionerdaemons.go @@ -274,15 +274,17 @@ func (c *Client) ServeProvisionerDaemon(ctx context.Context, req ServeProvisione } type ProvisionerKey struct { - ID uuid.UUID `json:"id" table:"-" format:"uuid"` - CreatedAt time.Time `json:"created_at" table:"created_at" format:"date-time"` - OrganizationID uuid.UUID `json:"organization" table:"organization_id" format:"uuid"` - Name string `json:"name" table:"name,default_sort"` + ID uuid.UUID `json:"id" table:"-" format:"uuid"` + CreatedAt time.Time `json:"created_at" table:"created_at" format:"date-time"` + OrganizationID uuid.UUID `json:"organization" table:"organization_id" format:"uuid"` + Name string `json:"name" table:"name,default_sort"` + Tags map[string]string `json:"tags" table:"tags"` // HashedSecret - never include the access token in the API response } type CreateProvisionerKeyRequest struct { - Name string `json:"name"` + Name string `json:"name"` + Tags map[string]string `json:"tags"` } type CreateProvisionerKeyResponse struct { diff --git a/docs/api/enterprise.md b/docs/api/enterprise.md index 876e6e9d5c554..dec875eebaac3 100644 --- a/docs/api/enterprise.md +++ b/docs/api/enterprise.md @@ -1389,7 +1389,11 @@ curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/provisi "created_at": "2019-08-24T14:15:22Z", "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "name": "string", - "organization": "452c1a86-a0af-475b-b03f-724878b0f387" + "organization": "452c1a86-a0af-475b-b03f-724878b0f387", + "tags": { + "property1": "string", + "property2": "string" + } } ] ``` @@ -1404,13 +1408,15 @@ curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/provisi Status Code **200** -| Name | Type | Required | Restrictions | Description | -| ---------------- | ----------------- | -------- | ------------ | ----------- | -| `[array item]` | array | false | | | -| `» created_at` | string(date-time) | false | | | -| `» id` | string(uuid) | false | | | -| `» name` | string | false | | | -| `» organization` | string(uuid) | false | | | +| Name | Type | Required | Restrictions | Description | +| ------------------- | ----------------- | -------- | ------------ | ----------- | +| `[array item]` | array | false | | | +| `» created_at` | string(date-time) | false | | | +| `» id` | string(uuid) | false | | | +| `» name` | string | false | | | +| `» organization` | string(uuid) | false | | | +| `» tags` | object | false | | | +| `»» [any property]` | string | false | | | To perform this operation, you must be authenticated. [Learn more](authentication.md). diff --git a/docs/api/schemas.md b/docs/api/schemas.md index e79e27377b324..8c8495a3def4c 100644 --- a/docs/api/schemas.md +++ b/docs/api/schemas.md @@ -3995,18 +3995,24 @@ CreateWorkspaceRequest provides options for creating a new workspace. Only one o "created_at": "2019-08-24T14:15:22Z", "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "name": "string", - "organization": "452c1a86-a0af-475b-b03f-724878b0f387" + "organization": "452c1a86-a0af-475b-b03f-724878b0f387", + "tags": { + "property1": "string", + "property2": "string" + } } ``` ### Properties -| Name | Type | Required | Restrictions | Description | -| -------------- | ------ | -------- | ------------ | ----------- | -| `created_at` | string | false | | | -| `id` | string | false | | | -| `name` | string | false | | | -| `organization` | string | false | | | +| Name | Type | Required | Restrictions | Description | +| ------------------ | ------ | -------- | ------------ | ----------- | +| `created_at` | string | false | | | +| `id` | string | false | | | +| `name` | string | false | | | +| `organization` | string | false | | | +| `tags` | object | false | | | +| » `[any property]` | string | false | | | ## codersdk.ProvisionerLogLevel diff --git a/enterprise/cli/provisionerkeys.go b/enterprise/cli/provisionerkeys.go index 8253d4826e164..9c2807cbf6439 100644 --- a/enterprise/cli/provisionerkeys.go +++ b/enterprise/cli/provisionerkeys.go @@ -33,7 +33,10 @@ func (r *RootCmd) provisionerKeys() *serpent.Command { } func (r *RootCmd) provisionerKeysCreate() *serpent.Command { - orgContext := agpl.NewOrganizationContext() + var ( + orgContext = agpl.NewOrganizationContext() + rawTags []string + ) client := new(codersdk.Client) cmd := &serpent.Command{ @@ -51,8 +54,14 @@ func (r *RootCmd) provisionerKeysCreate() *serpent.Command { return xerrors.Errorf("current organization: %w", err) } + tags, err := agpl.ParseProvisionerTags(rawTags) + if err != nil { + return err + } + res, err := client.CreateProvisionerKey(ctx, org.ID, codersdk.CreateProvisionerKeyRequest{ Name: inv.Args[0], + Tags: tags, }) if err != nil { return xerrors.Errorf("create provisioner key: %w", err) @@ -69,7 +78,15 @@ func (r *RootCmd) provisionerKeysCreate() *serpent.Command { }, } - cmd.Options = serpent.OptionSet{} + cmd.Options = serpent.OptionSet{ + { + Flag: "tag", + FlagShorthand: "t", + Env: "CODER_PROVISIONERD_TAGS", + Description: "Tags to filter provisioner jobs by.", + Value: serpent.StringArrayOf(&rawTags), + }, + } orgContext.AttachOptions(cmd) return cmd diff --git a/enterprise/cli/provisionerkeys_test.go b/enterprise/cli/provisionerkeys_test.go index dac764da616b9..5b62b1e9d46fd 100644 --- a/enterprise/cli/provisionerkeys_test.go +++ b/enterprise/cli/provisionerkeys_test.go @@ -41,7 +41,7 @@ func TestProvisionerKeys(t *testing.T) { ctx := testutil.Context(t, testutil.WaitMedium) inv, conf := newCLI( t, - "provisioner", "keys", "create", name, + "provisioner", "keys", "create", name, "--tag", "foo=bar", ) pty := ptytest.New(t) @@ -77,8 +77,10 @@ func TestProvisionerKeys(t *testing.T) { require.Contains(t, line, "NAME") require.Contains(t, line, "CREATED AT") require.Contains(t, line, "ORGANIZATION ID") + require.Contains(t, line, "TAGS") line = pty.ReadLine(ctx) require.Contains(t, line, strings.ToLower(name)) + require.Contains(t, line, "map[foo:bar]") inv, conf = newCLI( t, diff --git a/enterprise/coderd/provisionerdaemons_test.go b/enterprise/coderd/provisionerdaemons_test.go index 139a97199ee92..68055df5b77f5 100644 --- a/enterprise/coderd/provisionerdaemons_test.go +++ b/enterprise/coderd/provisionerdaemons_test.go @@ -559,7 +559,7 @@ func TestProvisionerDaemonServe(t *testing.T) { t.Run("ProvisionerKeyAuth", func(t *testing.T) { t.Parallel() - insertParams, token, err := provisionerkey.New(uuid.Nil, "dont-TEST-me") + insertParams, token, err := provisionerkey.New(uuid.Nil, "dont-TEST-me", nil) require.NoError(t, err) tcs := []struct { diff --git a/enterprise/coderd/provisionerkeys.go b/enterprise/coderd/provisionerkeys.go index 9cb66e2b7910d..a9f003682c6f2 100644 --- a/enterprise/coderd/provisionerkeys.go +++ b/enterprise/coderd/provisionerkeys.go @@ -54,7 +54,7 @@ func (api *API) postProvisionerKey(rw http.ResponseWriter, r *http.Request) { return } - params, token, err := provisionerkey.New(organization.ID, req.Name) + params, token, err := provisionerkey.New(organization.ID, req.Name, req.Tags) if err != nil { httpapi.InternalServerError(rw, err) return @@ -142,6 +142,7 @@ func convertProvisionerKeys(dbKeys []database.ProvisionerKey) []codersdk.Provisi CreatedAt: dbKey.CreatedAt, OrganizationID: dbKey.OrganizationID, Name: dbKey.Name, + Tags: dbKey.Tags, // HashedSecret - never include the access token in the API response }) } diff --git a/enterprise/coderd/provisionerkeys_test.go b/enterprise/coderd/provisionerkeys_test.go index 4c9408e0a27de..6becbe657ced6 100644 --- a/enterprise/coderd/provisionerkeys_test.go +++ b/enterprise/coderd/provisionerkeys_test.go @@ -69,9 +69,13 @@ func TestProvisionerKeys(t *testing.T) { require.NoError(t, err, "org admin list provisioner keys") require.Len(t, keys, 0, "org admin list provisioner keys") + tags := map[string]string{ + "my": "way", + } // org admin can create a provisioner key _, err = orgAdmin.CreateProvisionerKey(ctx, owner.OrganizationID, codersdk.CreateProvisionerKeyRequest{ Name: "Key", // case insensitive + Tags: tags, }) require.NoError(t, err, "org admin create provisioner key") @@ -97,6 +101,8 @@ func TestProvisionerKeys(t *testing.T) { keys, err = orgAdmin.ListProvisionerKeys(ctx, owner.OrganizationID) require.NoError(t, err, "org admin list provisioner keys") require.Len(t, keys, 1, "org admin list provisioner keys") + require.Equal(t, "key", keys[0].Name, "org admin list provisioner keys name matches") + require.EqualValues(t, tags, keys[0].Tags, "org admin list provisioner keys tags match") // org admin can delete a provisioner key err = orgAdmin.DeleteProvisionerKey(ctx, owner.OrganizationID, "key") // using lowercase here works diff --git a/site/src/api/typesGenerated.ts b/site/src/api/typesGenerated.ts index e0de1a184d6fc..2b69bf7b90424 100644 --- a/site/src/api/typesGenerated.ts +++ b/site/src/api/typesGenerated.ts @@ -237,6 +237,7 @@ export interface CreateOrganizationRequest { // From codersdk/provisionerdaemons.go export interface CreateProvisionerKeyRequest { readonly name: string; + readonly tags: Record; } // From codersdk/provisionerdaemons.go @@ -1002,6 +1003,7 @@ export interface ProvisionerKey { readonly created_at: string; readonly organization: string; readonly name: string; + readonly tags: Record; } // From codersdk/workspaceproxy.go pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy