mirror of
https://github.com/coder/coder.git
synced 2025-07-18 14:17:22 +00:00
feat: show user-auth provisioners (#14883)
Closes https://github.com/coder/coder/issues/14867 What this changes: - Displays `user-auth` grouped provisioners - Added tags to provisioners in cases where it matters <img width="1378" alt="image" src="https://github.com/user-attachments/assets/ecc8da0a-24b4-469d-99e7-aa1f183046b7"> --------- Co-authored-by: Ben Potter <ben@coder.com> Co-authored-by: McKayla Washburn <mckayla@hey.com>
This commit is contained in:
@ -147,9 +147,13 @@ func (api *API) provisionerKeyDaemons(rw http.ResponseWriter, r *http.Request) {
|
||||
|
||||
pkDaemons := []codersdk.ProvisionerKeyDaemons{}
|
||||
for _, key := range sdkKeys {
|
||||
// currently we exclude user-auth from this list
|
||||
// The key.OrganizationID for the `user-auth` key is hardcoded to
|
||||
// the default org in the database and we are overwriting it here
|
||||
// to be the correct org we used to query the list.
|
||||
// This will be changed when we update the `user-auth` keys to be
|
||||
// directly tied to a user ID.
|
||||
if key.ID.String() == codersdk.ProvisionerKeyIDUserAuth {
|
||||
continue
|
||||
key.OrganizationID = organization.ID
|
||||
}
|
||||
daemons := []codersdk.ProvisionerDaemon{}
|
||||
for _, daemon := range recentDaemons {
|
||||
|
@ -27,7 +27,7 @@ import { createDayString } from "utils/createDayString";
|
||||
import { docs } from "utils/docs";
|
||||
import { ProvisionerTag } from "./ProvisionerTag";
|
||||
|
||||
type ProvisionerGroupType = "builtin" | "psk" | "key";
|
||||
type ProvisionerGroupType = "builtin" | "userAuth" | "psk" | "key";
|
||||
|
||||
interface ProvisionerGroupProps {
|
||||
readonly buildInfo: BuildInfoResponse;
|
||||
@ -103,7 +103,8 @@ export const ProvisionerGroup: FC<ProvisionerGroupProps> = ({
|
||||
: `${provisionersWithWarnings} provisioners`;
|
||||
|
||||
const hasMultipleTagVariants =
|
||||
type === "psk" && provisioners.some((it) => !isSimpleTagSet(it.tags));
|
||||
(type === "psk" || type === "userAuth") &&
|
||||
provisioners.some((it) => !isSimpleTagSet(it.tags));
|
||||
|
||||
return (
|
||||
<div
|
||||
@ -143,6 +144,8 @@ export const ProvisionerGroup: FC<ProvisionerGroupProps> = ({
|
||||
</>
|
||||
)}
|
||||
|
||||
{type === "userAuth" && <UserAuthProvisionerTitle />}
|
||||
|
||||
{type === "psk" && <PskProvisionerTitle />}
|
||||
{type === "key" && (
|
||||
<h4 css={styles.groupTitle}>Key group – {keyName}</h4>
|
||||
@ -249,7 +252,7 @@ export const ProvisionerGroup: FC<ProvisionerGroupProps> = ({
|
||||
</span>
|
||||
</div>
|
||||
{hasMultipleTagVariants && (
|
||||
<PskProvisionerTags tags={provisioner.tags} />
|
||||
<InlineProvisionerTags tags={provisioner.tags} />
|
||||
)}
|
||||
</Stack>
|
||||
</div>
|
||||
@ -335,11 +338,11 @@ const ProvisionerVersionPopover: FC<ProvisionerVersionPopoverProps> = ({
|
||||
);
|
||||
};
|
||||
|
||||
interface PskProvisionerTagsProps {
|
||||
interface InlineProvisionerTagsProps {
|
||||
tags: Record<string, string>;
|
||||
}
|
||||
|
||||
const PskProvisionerTags: FC<PskProvisionerTagsProps> = ({ tags }) => {
|
||||
const InlineProvisionerTags: FC<InlineProvisionerTagsProps> = ({ tags }) => {
|
||||
const daemonScope = tags.scope || "organization";
|
||||
const iconScope =
|
||||
daemonScope === "organization" ? <BusinessIcon /> : <PersonIcon />;
|
||||
@ -413,6 +416,30 @@ const BuiltinProvisionerTitle: FC = () => {
|
||||
);
|
||||
};
|
||||
|
||||
const UserAuthProvisionerTitle: FC = () => {
|
||||
return (
|
||||
<h4 css={styles.groupTitle}>
|
||||
<Stack direction="row" alignItems="end" spacing={1}>
|
||||
<span>User-authenticated provisioners</span>
|
||||
<HelpTooltip>
|
||||
<HelpTooltipTrigger />
|
||||
<HelpTooltipContent>
|
||||
<HelpTooltipTitle>User-authenticated provisioners</HelpTooltipTitle>
|
||||
<HelpTooltipText>
|
||||
These provisioners are connected by users using the{" "}
|
||||
<code>coder</code> CLI, and are authorized by the users
|
||||
credentials. They can be tagged to only run provisioner jobs for
|
||||
that user. User-authenticated provisioners are only available for
|
||||
the default organization.{" "}
|
||||
<Link href={docs("/")}>Learn more…</Link>
|
||||
</HelpTooltipText>
|
||||
</HelpTooltipContent>
|
||||
</HelpTooltip>
|
||||
</Stack>
|
||||
</h4>
|
||||
);
|
||||
};
|
||||
|
||||
const PskProvisionerTitle: FC = () => {
|
||||
return (
|
||||
<h4 css={styles.groupTitle}>
|
||||
|
@ -7,6 +7,7 @@ import {
|
||||
MockProvisionerBuiltinKey,
|
||||
MockProvisionerKey,
|
||||
MockProvisionerPskKey,
|
||||
MockProvisionerUserAuthKey,
|
||||
MockProvisionerWithTags,
|
||||
MockUserProvisioner,
|
||||
mockApiError,
|
||||
@ -79,6 +80,17 @@ export const Provisioners: Story = {
|
||||
name: `ケイラ-${i}`,
|
||||
})),
|
||||
},
|
||||
{
|
||||
key: MockProvisionerUserAuthKey,
|
||||
daemons: [
|
||||
MockUserProvisioner,
|
||||
{
|
||||
...MockUserProvisioner,
|
||||
id: "mock-user-provisioner-2",
|
||||
name: "Test User Provisioner 2",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
play: async ({ step }) => {
|
||||
|
@ -110,28 +110,16 @@ const ViewContent: FC<ViewContentProps> = ({ buildInfo, provisioners }) => {
|
||||
</div>
|
||||
)}
|
||||
<Stack spacing={4.5}>
|
||||
{provisioners.map((group) => {
|
||||
const type = getGroupType(group.key);
|
||||
|
||||
// We intentionally hide user-authenticated provisioners for now
|
||||
// because there are 1. some grouping issues on the backend and 2. we
|
||||
// should ideally group them by the user who authenticated them, and
|
||||
// not just lump them all together.
|
||||
if (type === "userAuth") {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<ProvisionerGroup
|
||||
key={group.key.id}
|
||||
buildInfo={buildInfo}
|
||||
keyName={group.key.name}
|
||||
keyTags={group.key.tags}
|
||||
type={type}
|
||||
provisioners={group.daemons}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
{provisioners.map((group) => (
|
||||
<ProvisionerGroup
|
||||
key={group.key.id}
|
||||
buildInfo={buildInfo}
|
||||
keyName={group.key.name}
|
||||
keyTags={group.key.tags}
|
||||
type={getGroupType(group.key)}
|
||||
provisioners={group.daemons}
|
||||
/>
|
||||
))}
|
||||
</Stack>
|
||||
</>
|
||||
);
|
||||
|
@ -610,7 +610,7 @@ export const MockProvisioner2: TypesGen.ProvisionerDaemon = {
|
||||
};
|
||||
|
||||
export const MockUserProvisioner: TypesGen.ProvisionerDaemon = {
|
||||
...MockProvisioner,
|
||||
...MockUserAuthProvisioner,
|
||||
id: "test-user-provisioner",
|
||||
name: "Test User Provisioner",
|
||||
tags: { scope: "user", owner: "12345678-abcd-1234-abcd-1234567890abcd" },
|
||||
|
Reference in New Issue
Block a user