Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
This commit is contained in:
Marc 'risson' Schmitt
2025-06-06 16:46:57 +02:00
parent e4c1e5aed0
commit cae03beb6d
9 changed files with 35 additions and 391 deletions

View File

@ -222,28 +222,26 @@ def _outpost_single_update(outpost: Outpost, layer=None):
@actor
def outpost_connection_discovery():
"""Checks the local environment and create Service connections."""
self: Task = CurrentTask.get_task()
messages = []
self = CurrentTask.get_task()
if not CONFIG.get_bool("outposts.discover"):
messages.append("Outpost integration discovery is disabled")
self.set_status(TaskStatus.SUCCESSFUL, *messages)
self.info("Outpost integration discovery is disabled")
return
# Explicitly check against token filename, as that's
# only present when the integration is enabled
if Path(SERVICE_TOKEN_FILENAME).exists():
messages.append("Detected in-cluster Kubernetes Config")
self.info("Detected in-cluster Kubernetes Config")
if not KubernetesServiceConnection.objects.filter(local=True).exists():
messages.append("Created Service Connection for in-cluster")
self.info("Created Service Connection for in-cluster")
KubernetesServiceConnection.objects.create(
name="Local Kubernetes Cluster", local=True, kubeconfig={}
)
# For development, check for the existence of a kubeconfig file
kubeconfig_path = Path(KUBE_CONFIG_DEFAULT_LOCATION).expanduser()
if kubeconfig_path.exists():
messages.append("Detected kubeconfig")
self.info("Detected kubeconfig")
kubeconfig_local_name = f"k8s-{gethostname()}"
if not KubernetesServiceConnection.objects.filter(name=kubeconfig_local_name).exists():
messages.append("Creating kubeconfig Service Connection")
self.info("Creating kubeconfig Service Connection")
with kubeconfig_path.open("r", encoding="utf8") as _kubeconfig:
KubernetesServiceConnection.objects.create(
name=kubeconfig_local_name,
@ -252,12 +250,11 @@ def outpost_connection_discovery():
unix_socket_path = urlparse(DEFAULT_UNIX_SOCKET).path
socket = Path(unix_socket_path)
if socket.exists() and access(socket, R_OK):
messages.append("Detected local docker socket")
self.info("Detected local docker socket")
if len(DockerServiceConnection.objects.filter(local=True)) == 0:
messages.append("Created Service Connection for docker")
self.info("Created Service Connection for docker")
DockerServiceConnection.objects.create(
name="Local Docker connection",
local=True,
url=unix_socket_path,
)
self.set_status(TaskStatus.SUCCESSFUL, *messages)

View File

@ -343,7 +343,9 @@ USE_TZ = True
LOCALE_PATHS = ["./locale"]
# Sentry integration
env = get_env()
_ERROR_REPORTING = CONFIG.get_bool("error_reporting.enabled", False)
if _ERROR_REPORTING:
@ -466,10 +468,6 @@ try:
except ImportError:
pass
# Import schedules after other apps since it relies on tasks and ScheduledModel being
# registered for its startup.
TENANT_APPS.append("authentik.tasks.schedules")
# Load subapps's settings
for _app in set(SHARED_APPS + TENANT_APPS):
@ -478,5 +476,9 @@ for _app in set(SHARED_APPS + TENANT_APPS):
_update_settings(f"{_app}.settings")
_update_settings("data.user_settings")
# Import schedules after other apps since it relies on tasks and ScheduledModel being
# registered for its startup.
TENANT_APPS.append("authentik.tasks.schedules")
SHARED_APPS = list(OrderedDict.fromkeys(SHARED_APPS + TENANT_APPS))
INSTALLED_APPS = list(OrderedDict.fromkeys(SHARED_APPS + TENANT_APPS))

View File

@ -1,4 +1,5 @@
import dramatiq
from django.conf import settings
from dramatiq.broker import Broker, get_broker
from dramatiq.encoder import PickleEncoder
from dramatiq.middleware import (

View File

@ -1,6 +1,7 @@
from authentik.blueprints.apps import ManagedAppConfig
from authentik.lib.utils.reflection import get_apps
from authentik.tasks.schedules.lib import ScheduleSpec
from django.conf import settings
class AuthentikTasksSchedulesConfig(ManagedAppConfig):

View File

@ -7503,13 +7503,11 @@
"authentik_events.delete_notificationrule",
"authentik_events.delete_notificationtransport",
"authentik_events.delete_notificationwebhookmapping",
"authentik_events.run_task",
"authentik_events.view_event",
"authentik_events.view_notification",
"authentik_events.view_notificationrule",
"authentik_events.view_notificationtransport",
"authentik_events.view_notificationwebhookmapping",
"authentik_events.view_systemtask",
"authentik_flows.add_flow",
"authentik_flows.add_flowstagebinding",
"authentik_flows.add_flowtoken",
@ -14241,13 +14239,11 @@
"authentik_events.delete_notificationrule",
"authentik_events.delete_notificationtransport",
"authentik_events.delete_notificationwebhookmapping",
"authentik_events.run_task",
"authentik_events.view_event",
"authentik_events.view_notification",
"authentik_events.view_notificationrule",
"authentik_events.view_notificationtransport",
"authentik_events.view_notificationwebhookmapping",
"authentik_events.view_systemtask",
"authentik_flows.add_flow",
"authentik_flows.add_flowstagebinding",
"authentik_flows.add_flowtoken",

View File

@ -347,35 +347,6 @@ paths:
schema:
$ref: '#/components/schemas/GenericError'
description: ''
/admin/workers/:
get:
operationId: admin_workers_list
description: Get currently connected worker count.
tags:
- admin
security:
- authentik: []
responses:
'200':
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Worker'
description: ''
'400':
content:
application/json:
schema:
$ref: '#/components/schemas/ValidationError'
description: ''
'403':
content:
application/json:
schema:
$ref: '#/components/schemas/GenericError'
description: ''
/authenticators/admin/all/:
get:
operationId: authenticators_admin_all_list
@ -8123,145 +8094,6 @@ paths:
schema:
$ref: '#/components/schemas/GenericError'
description: ''
/events/system_tasks/:
get:
operationId: events_system_tasks_list
description: Read-only view set that returns all background tasks
parameters:
- in: query
name: name
schema:
type: string
- name: ordering
required: false
in: query
description: Which field to use when ordering the results.
schema:
type: string
- name: page
required: false
in: query
description: A page number within the paginated result set.
schema:
type: integer
- name: page_size
required: false
in: query
description: Number of results to return per page.
schema:
type: integer
- name: search
required: false
in: query
description: A search term.
schema:
type: string
- in: query
name: status
schema:
type: string
enum:
- error
- successful
- unknown
- warning
- in: query
name: uid
schema:
type: string
tags:
- events
security:
- authentik: []
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/PaginatedSystemTaskList'
description: ''
'400':
content:
application/json:
schema:
$ref: '#/components/schemas/ValidationError'
description: ''
'403':
content:
application/json:
schema:
$ref: '#/components/schemas/GenericError'
description: ''
/events/system_tasks/{uuid}/:
get:
operationId: events_system_tasks_retrieve
description: Read-only view set that returns all background tasks
parameters:
- in: path
name: uuid
schema:
type: string
format: uuid
description: A UUID string identifying this System Task.
required: true
tags:
- events
security:
- authentik: []
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/SystemTask'
description: ''
'400':
content:
application/json:
schema:
$ref: '#/components/schemas/ValidationError'
description: ''
'403':
content:
application/json:
schema:
$ref: '#/components/schemas/GenericError'
description: ''
/events/system_tasks/{uuid}/run/:
post:
operationId: events_system_tasks_run_create
description: Run task
parameters:
- in: path
name: uuid
schema:
type: string
format: uuid
description: A UUID string identifying this System Task.
required: true
tags:
- events
security:
- authentik: []
responses:
'204':
description: Task retried successfully
'404':
description: Task not found
'500':
description: Failed to retry task
'400':
content:
application/json:
schema:
$ref: '#/components/schemas/ValidationError'
description: ''
'403':
content:
application/json:
schema:
$ref: '#/components/schemas/GenericError'
description: ''
/events/transports/:
get:
operationId: events_transports_list
@ -19699,8 +19531,6 @@ paths:
schema:
$ref: '#/components/schemas/SyncStatus'
description: ''
'404':
description: Task not found
'400':
content:
application/json:
@ -20742,8 +20572,6 @@ paths:
schema:
$ref: '#/components/schemas/SyncStatus'
description: ''
'404':
description: Task not found
'400':
content:
application/json:
@ -23277,8 +23105,6 @@ paths:
schema:
$ref: '#/components/schemas/SyncStatus'
description: ''
'404':
description: Task not found
'400':
content:
application/json:
@ -40901,10 +40727,6 @@ paths:
name: queue_name
schema:
type: string
- in: query
name: schedule_uid
schema:
type: string
- name: search
required: false
in: query
@ -47741,14 +47563,8 @@ components:
is_running:
type: boolean
readOnly: true
tasks:
type: array
items:
$ref: '#/components/schemas/SystemTask'
readOnly: true
required:
- is_running
- tasks
KubernetesServiceConnection:
type: object
description: KubernetesServiceConnection Serializer
@ -51645,18 +51461,6 @@ components:
required:
- pagination
- results
PaginatedSystemTaskList:
type: object
properties:
pagination:
$ref: '#/components/schemas/Pagination'
results:
type: array
items:
$ref: '#/components/schemas/SystemTask'
required:
- pagination
- results
PaginatedTOTPDeviceList:
type: object
properties:
@ -59997,14 +59801,8 @@ components:
is_running:
type: boolean
readOnly: true
tasks:
type: array
items:
$ref: '#/components/schemas/SystemTask'
readOnly: true
required:
- is_running
- tasks
SystemInfo:
type: object
description: Get system information.
@ -60080,65 +59878,6 @@ components:
- http_is_secure
- runtime
- server_time
SystemTask:
type: object
description: Serialize TaskInfo and TaskResult
properties:
uuid:
type: string
format: uuid
readOnly: true
name:
type: string
full_name:
type: string
description: Get full name with UID
readOnly: true
uid:
type: string
description:
type: string
start_timestamp:
type: string
format: date-time
readOnly: true
finish_timestamp:
type: string
format: date-time
readOnly: true
duration:
type: number
format: double
readOnly: true
status:
$ref: '#/components/schemas/SystemTaskStatusEnum'
messages:
type: array
items:
$ref: '#/components/schemas/LogEvent'
expires:
type: string
format: date-time
nullable: true
expiring:
type: boolean
required:
- description
- duration
- finish_timestamp
- full_name
- messages
- name
- start_timestamp
- status
- uuid
SystemTaskStatusEnum:
enum:
- unknown
- successful
- warning
- error
type: string
TOTPDevice:
type: object
description: Serializer for totp authenticator devices
@ -60190,10 +59929,9 @@ components:
type: string
format: date-time
description: Task last modified time
schedule_uid:
type: string
uid:
type: string
readOnly: true
messages:
type: array
items:
@ -60201,6 +59939,7 @@ components:
required:
- actor_name
- messages
- uid
Tenant:
type: object
description: Tenant Serializer
@ -61848,19 +61587,6 @@ components:
required:
- aaguid
- description
Worker:
type: object
properties:
worker_id:
type: string
version:
type: string
version_matching:
type: boolean
required:
- version
- version_matching
- worker_id
modelRequest:
oneOf:
- $ref: '#/components/schemas/GoogleWorkspaceProviderRequest'

View File

@ -16,10 +16,10 @@ export const ROUTES: Route[] = [
await import("@goauthentik/admin/admin-overview/DashboardUserPage");
return html`<ak-admin-dashboard-users></ak-admin-dashboard-users>`;
}),
new Route(new RegExp("^/administration/system-tasks$"), async () => {
await import("@goauthentik/admin/system-tasks/SystemTaskListPage");
return html`<ak-system-task-list></ak-system-task-list>`;
}),
// new Route(new RegExp("^/administration/system-tasks$"), async () => {
// await import("@goauthentik/admin/system-tasks/SystemTaskListPage");
// return html`<ak-system-task-list></ak-system-task-list>`;
// }),
new Route(new RegExp("^/core/providers$"), async () => {
await import("@goauthentik/admin/providers/ProviderListPage");
return html`<ak-provider-list></ak-provider-list>`;

View File

@ -7,7 +7,7 @@ import "#admin/admin-overview/cards/VersionStatusCard";
import "#admin/admin-overview/cards/WorkerStatusCard";
import "#admin/admin-overview/charts/AdminLoginAuthorizeChart";
import "#admin/admin-overview/charts/OutpostStatusChart";
import "#admin/admin-overview/charts/SyncStatusChart";
// import "#admin/admin-overview/charts/SyncStatusChart";
import { me } from "#common/users";
import "#components/ak-page-header";
import { AKElement } from "#elements/Base";
@ -110,13 +110,15 @@ export class AdminOverviewPage extends AdminOverviewBase {
<ak-admin-status-chart-outpost></ak-admin-status-chart-outpost>
</ak-aggregate-card>
</div>
<div
class="pf-l-grid__item pf-m-12-col pf-m-12-col-on-xl pf-m-4-col-on-2xl"
>
<ak-aggregate-card icon="fa fa-sync-alt" header=${msg("Sync status")}>
<ak-admin-status-chart-sync></ak-admin-status-chart-sync>
</ak-aggregate-card>
</div>
<!-- <div -->
<!-- class="pf-l-grid__item pf-m-12-col pf-m-12-col-on-xl pf-m-4-col-on-2xl" -->
<!-- > -->
<!-- <ak-aggregate-card icon="fa fa-sync-alt" header=${msg(
"Sync status",
)}> -->
<!-- <ak-admin-status-chart-sync></ak-admin-status-chart-sync> -->
<!-- </ak-aggregate-card> -->
<!-- </div> -->
<div class="pf-l-grid__item pf-m-12-col">
<hr class="pf-c-divider" />
</div>

View File

@ -1,14 +1,12 @@
import { EVENT_REFRESH } from "@goauthentik/common/constants";
import { formatElapsedTime } from "@goauthentik/common/temporal";
import "@goauthentik/components/ak-status-label";
import { AKElement } from "@goauthentik/elements/Base";
import "@goauthentik/elements/EmptyState";
import "@goauthentik/elements/buttons/ActionButton";
import "@goauthentik/elements/events/LogViewer";
import { PaginatedResponse, Table, TableColumn } from "@goauthentik/elements/table/Table";
import { msg } from "@lit/localize";
import { CSSResult, TemplateResult, css, html } from "lit";
import { CSSResult, TemplateResult, html } from "lit";
import { customElement, property, state } from "lit/decorators.js";
import PFButton from "@patternfly/patternfly/components/Button/button.css";
@ -16,82 +14,7 @@ import PFCard from "@patternfly/patternfly/components/Card/card.css";
import PFTable from "@patternfly/patternfly/components/Table/table.css";
import PFBase from "@patternfly/patternfly/patternfly-base.css";
import { SyncStatus, SystemTask, SystemTaskStatusEnum } from "@goauthentik/api";
@customElement("ak-sync-status-table")
export class SyncStatusTable extends Table<SystemTask> {
@property({ attribute: false })
tasks: SystemTask[] = [];
expandable = true;
static get styles() {
return super.styles.concat(css`
code:not(:last-of-type)::after {
content: "-";
margin: 0 0.25rem;
}
`);
}
async apiEndpoint(): Promise<PaginatedResponse<SystemTask>> {
if (this.tasks.length === 1) {
this.expandedElements = this.tasks;
}
return {
pagination: {
next: 0,
previous: 0,
count: this.tasks.length,
current: 1,
totalPages: 1,
startIndex: 0,
endIndex: this.tasks.length,
},
results: this.tasks,
};
}
columns(): TableColumn[] {
return [
new TableColumn(msg("Task")),
new TableColumn(msg("Status")),
new TableColumn(msg("Finished")),
];
}
row(item: SystemTask): TemplateResult[] {
const nameParts = item.fullName.split(":");
nameParts.shift();
return [
html`<div>${item.name}</div>
<small>${nameParts.map((part) => html`<code>${part}</code>`)}</small>`,
html`<ak-status-label
?good=${item.status === SystemTaskStatusEnum.Successful}
good-label=${msg("Finished successfully")}
bad-label=${msg("Finished with errors")}
></ak-status-label>`,
html`<div>${formatElapsedTime(item.finishTimestamp)}</div>
<small>${item.finishTimestamp.toLocaleString()}</small>`,
];
}
renderExpanded(item: SystemTask): TemplateResult {
return html`<td role="cell" colspan="4">
<div class="pf-c-table__expandable-row-content">
<ak-log-viewer .logs=${item?.messages}></ak-log-viewer>
</div>
</td>`;
}
renderToolbarContainer() {
return html``;
}
renderTablePagination() {
return html``;
}
}
import { SyncStatus } from "@goauthentik/api";
@customElement("ak-sync-status-card")
export class SyncStatusCard extends AKElement {
@ -129,10 +52,7 @@ export class SyncStatusCard extends AKElement {
if (this.syncState.isRunning) {
return html`${msg("Sync currently running.")}`;
}
if (this.syncState.tasks.length < 1) {
return html`${msg("Not synced yet.")}`;
}
return html`<ak-sync-status-table .tasks=${this.syncState.tasks}></ak-sync-status-table>`;
return html`${msg("No synchronization currently running.")}`;
}
render(): TemplateResult {
@ -187,7 +107,6 @@ export class SyncStatusCard extends AKElement {
declare global {
interface HTMLElementTagNameMap {
"ak-sync-status-table": SyncStatusTable;
"ak-sync-status-card": SyncStatusCard;
}
}