apache-airflow-providers-edge3 2.0.0rc1__py3-none-any.whl → 3.0.1rc1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. airflow/providers/edge3/__init__.py +1 -1
  2. airflow/providers/edge3/cli/api_client.py +30 -28
  3. airflow/providers/edge3/cli/dataclasses.py +3 -10
  4. airflow/providers/edge3/cli/definition.py +261 -0
  5. airflow/providers/edge3/cli/edge_command.py +8 -206
  6. airflow/providers/edge3/cli/worker.py +226 -198
  7. airflow/providers/edge3/example_dags/win_notepad.py +1 -1
  8. airflow/providers/edge3/executors/edge_executor.py +24 -49
  9. airflow/providers/edge3/get_provider_info.py +1 -0
  10. airflow/providers/edge3/models/edge_job.py +1 -2
  11. airflow/providers/edge3/models/edge_worker.py +61 -16
  12. airflow/providers/edge3/plugins/edge_executor_plugin.py +1 -1
  13. airflow/providers/edge3/plugins/www/dist/main.umd.cjs +8 -8
  14. airflow/providers/edge3/plugins/www/package.json +32 -27
  15. airflow/providers/edge3/plugins/www/pnpm-lock.yaml +1625 -1716
  16. airflow/providers/edge3/plugins/www/src/global.d.ts +24 -0
  17. airflow/providers/edge3/plugins/www/src/layouts/NavTabs.tsx +25 -3
  18. airflow/providers/edge3/plugins/www/src/main.tsx +6 -1
  19. airflow/providers/edge3/plugins/www/src/theme.ts +1 -1
  20. airflow/providers/edge3/worker_api/datamodels.py +12 -1
  21. airflow/providers/edge3/worker_api/routes/jobs.py +21 -8
  22. airflow/providers/edge3/worker_api/routes/logs.py +1 -1
  23. airflow/providers/edge3/worker_api/routes/worker.py +16 -3
  24. {apache_airflow_providers_edge3-2.0.0rc1.dist-info → apache_airflow_providers_edge3-3.0.1rc1.dist-info}/METADATA +14 -10
  25. {apache_airflow_providers_edge3-2.0.0rc1.dist-info → apache_airflow_providers_edge3-3.0.1rc1.dist-info}/RECORD +29 -29
  26. {apache_airflow_providers_edge3-2.0.0rc1.dist-info → apache_airflow_providers_edge3-3.0.1rc1.dist-info}/licenses/NOTICE +1 -1
  27. airflow/providers/edge3/plugins/templates/edge_worker_hosts.html +0 -175
  28. airflow/providers/edge3/plugins/templates/edge_worker_jobs.html +0 -69
  29. {apache_airflow_providers_edge3-2.0.0rc1.dist-info → apache_airflow_providers_edge3-3.0.1rc1.dist-info}/WHEEL +0 -0
  30. {apache_airflow_providers_edge3-2.0.0rc1.dist-info → apache_airflow_providers_edge3-3.0.1rc1.dist-info}/entry_points.txt +0 -0
  31. {apache_airflow_providers_edge3-2.0.0rc1.dist-info → apache_airflow_providers_edge3-3.0.1rc1.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,24 @@
1
+ /*!
2
+ * Licensed to the Apache Software Foundation (ASF) under one
3
+ * or more contributor license agreements. See the NOTICE file
4
+ * distributed with this work for additional information
5
+ * regarding copyright ownership. The ASF licenses this file
6
+ * to you under the Apache License, Version 2.0 (the
7
+ * "License"); you may not use this file except in compliance
8
+ * with the License. You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing,
13
+ * software distributed under the License is distributed on an
14
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
+ * KIND, either express or implied. See the License for the
16
+ * specific language governing permissions and limitations
17
+ * under the License.
18
+ */
19
+
20
+ export type global = object;
21
+
22
+ declare global {
23
+ var ChakraUISystem: SystemContext | undefined;
24
+ }
@@ -17,10 +17,13 @@
17
17
  * under the License.
18
18
  */
19
19
  import { Center, Flex } from "@chakra-ui/react";
20
+ import axios from "axios";
21
+ import { useQuery } from "@tanstack/react-query";
20
22
  import { useRef, type ReactNode } from "react";
21
23
  import { NavLink } from "react-router-dom";
22
24
 
23
25
  import { useContainerWidth } from "src/utils";
26
+ import { lte } from "semver";
24
27
 
25
28
  type Props = {
26
29
  readonly tabs: Array<{ icon?: ReactNode; label: string; value: string }>;
@@ -30,10 +33,29 @@ export const NavTabs = ({ tabs }: Props) => {
30
33
  const containerRef = useRef<HTMLDivElement>(null);
31
34
  const containerWidth = useContainerWidth(containerRef);
32
35
 
36
+ const { data } = useQuery<{version: string, git_version: string | null}>({
37
+ queryFn: async () => {
38
+ const res = await axios.get("/api/v2/version");
39
+ return res.data;
40
+ },
41
+ queryKey: ["appVersion"],
42
+ });
43
+
44
+ let legacyRouterNavigation: boolean | undefined = undefined;
45
+
46
+ if (data) {
47
+ const airflowCoreVersion = data.version;
48
+ if (lte(airflowCoreVersion, "3.1.6")) {
49
+ legacyRouterNavigation = true;
50
+ } else {
51
+ legacyRouterNavigation = false;
52
+ }
53
+ }
54
+
33
55
  return (
34
56
  <Flex alignItems="center" borderBottomWidth={1} mb={2} ref={containerRef}>
35
- {tabs.map(({ icon, label, value }) => (
36
- <NavLink end key={value} title={label} to={value}>
57
+ {legacyRouterNavigation !== undefined ? tabs.map(({ icon, label, value }) => (
58
+ <NavLink end key={value} title={label} to={legacyRouterNavigation ? value : `../${value}`} relative={legacyRouterNavigation ? "route" : "path"}>
37
59
  {({ isActive }) => (
38
60
  <Center
39
61
  borderBottomColor="border.info"
@@ -50,7 +72,7 @@ export const NavTabs = ({ tabs }: Props) => {
50
72
  </Center>
51
73
  )}
52
74
  </NavLink>
53
- ))}
75
+ )): undefined}
54
76
  </Flex>
55
77
  );
56
78
  };
@@ -24,7 +24,7 @@ import { FC } from "react";
24
24
  import { ColorModeProvider } from "src/context/colorMode";
25
25
  import { EdgeLayout } from "src/layouts/EdgeLayout";
26
26
 
27
- import { system } from "./theme";
27
+ import { localSystem } from "./theme";
28
28
 
29
29
  export type PluginComponentProps = object;
30
30
 
@@ -37,6 +37,11 @@ const PluginComponent: FC<PluginComponentProps> = () => {
37
37
  const baseUrl = new URL(baseHref, globalThis.location.origin);
38
38
  OpenAPI.BASE = baseUrl.pathname.replace(/\/$/, ""); // Remove trailing slash
39
39
 
40
+ // Use the globalChakraUISystem provided by the Airflow Core UI,
41
+ // so the plugin has a consistent theming with the host Airflow UI,
42
+ // fallback to localSystem for local development.
43
+ const system = globalThis.ChakraUISystem ?? localSystem;
44
+
40
45
  const queryClient = new QueryClient({
41
46
  defaultOptions: {
42
47
  queries: {
@@ -394,7 +394,7 @@ export const customConfig = defineConfig({
394
394
  },
395
395
  });
396
396
 
397
- export const system = createSystem(defaultConfig, customConfig);
397
+ export const localSystem = createSystem(defaultConfig, customConfig);
398
398
 
399
399
  // Utility function to resolve CSS variables to their computed values
400
400
  // See: https://github.com/chakra-ui/panda/discussions/2200
@@ -26,7 +26,7 @@ from fastapi import Path
26
26
  from pydantic import BaseModel, Field
27
27
 
28
28
  from airflow.executors.workloads import ExecuteTask # noqa: TCH001
29
- from airflow.models.taskinstancekey import TaskInstanceKey
29
+ from airflow.providers.common.compat.sdk import TaskInstanceKey
30
30
  from airflow.providers.edge3.models.edge_worker import EdgeWorkerState # noqa: TCH001
31
31
 
32
32
 
@@ -99,6 +99,17 @@ class EdgeJobFetched(EdgeJobBase):
99
99
  ]
100
100
  concurrency_slots: Annotated[int, Field(description="Number of concurrency slots the job requires.")]
101
101
 
102
+ @property
103
+ def identifier(self) -> str:
104
+ """Get a human readable identifier for the edge job."""
105
+ return (
106
+ f"dag_id={self.dag_id} "
107
+ f"task_id={self.task_id} "
108
+ f"run_id={self.run_id} "
109
+ f"map_index={self.map_index} "
110
+ f"try_number={self.try_number}"
111
+ )
112
+
102
113
 
103
114
  class WorkerQueuesBase(BaseModel):
104
115
  """Queues that a worker supports to run jobs on."""
@@ -80,14 +80,19 @@ def fetch(
80
80
  job: EdgeJobModel | None = session.scalar(query)
81
81
  if not job:
82
82
  return None
83
- job.state = TaskInstanceState.RUNNING
83
+ job.state = TaskInstanceState.RESTARTING # keep this intermediate state until worker sets to running
84
84
  job.edge_worker = worker_name
85
85
  job.last_update = timezone.utcnow()
86
86
  session.commit()
87
87
  # Edge worker does not backport emitted Airflow metrics, so export some metrics
88
88
  tags = {"dag_id": job.dag_id, "task_id": job.task_id, "queue": job.queue}
89
- Stats.incr(f"edge_worker.ti.start.{job.queue}.{job.dag_id}.{job.task_id}", tags=tags)
90
- Stats.incr("edge_worker.ti.start", tags=tags)
89
+ try:
90
+ from airflow.sdk._shared.observability.metrics.dual_stats_manager import DualStatsManager
91
+
92
+ DualStatsManager.incr("edge_worker.ti.start", tags=tags)
93
+ except ImportError:
94
+ Stats.incr(f"edge_worker.ti.start.{job.queue}.{job.dag_id}.{job.task_id}", tags=tags)
95
+ Stats.incr("edge_worker.ti.start", tags=tags)
91
96
  return EdgeJobFetched(
92
97
  dag_id=job.dag_id,
93
98
  task_id=job.task_id,
@@ -140,11 +145,19 @@ def state(
140
145
  "queue": job.queue,
141
146
  "state": str(state),
142
147
  }
143
- Stats.incr(
144
- f"edge_worker.ti.finish.{job.queue}.{state}.{job.dag_id}.{job.task_id}",
145
- tags=tags,
146
- )
147
- Stats.incr("edge_worker.ti.finish", tags=tags)
148
+ try:
149
+ from airflow.sdk._shared.observability.metrics.dual_stats_manager import DualStatsManager
150
+
151
+ DualStatsManager.incr(
152
+ "edge_worker.ti.finish",
153
+ tags=tags,
154
+ )
155
+ except ImportError:
156
+ Stats.incr(
157
+ f"edge_worker.ti.finish.{job.queue}.{state}.{job.dag_id}.{job.task_id}",
158
+ tags=tags,
159
+ )
160
+ Stats.incr("edge_worker.ti.finish", tags=tags)
148
161
 
149
162
  query2 = (
150
163
  update(EdgeJobModel)
@@ -28,7 +28,7 @@ from airflow.api_fastapi.common.router import AirflowRouter
28
28
  from airflow.api_fastapi.core_api.openapi.exceptions import create_openapi_http_exception_doc
29
29
  from airflow.configuration import conf
30
30
  from airflow.models.taskinstance import TaskInstance
31
- from airflow.models.taskinstancekey import TaskInstanceKey
31
+ from airflow.providers.common.compat.sdk import TaskInstanceKey
32
32
  from airflow.providers.edge3.models.edge_logs import EdgeLogsModel
33
33
  from airflow.providers.edge3.worker_api.auth import jwt_token_authorization_rest
34
34
  from airflow.providers.edge3.worker_api.datamodels import PushLogsBody, WorkerApiDocs
@@ -26,7 +26,7 @@ from sqlalchemy import select
26
26
  from airflow.api_fastapi.common.db.common import SessionDep # noqa: TC001
27
27
  from airflow.api_fastapi.common.router import AirflowRouter
28
28
  from airflow.api_fastapi.core_api.openapi.exceptions import create_openapi_http_exception_doc
29
- from airflow.providers.common.compat.sdk import Stats, timezone
29
+ from airflow.providers.common.compat.sdk import timezone
30
30
  from airflow.providers.edge3.models.edge_worker import EdgeWorkerModel, EdgeWorkerState, set_metrics
31
31
  from airflow.providers.edge3.worker_api.auth import jwt_token_authorization_rest
32
32
  from airflow.providers.edge3.worker_api.datamodels import (
@@ -212,8 +212,21 @@ def set_state(
212
212
  worker.sysinfo = json.dumps(body.sysinfo)
213
213
  worker.last_update = timezone.utcnow()
214
214
  session.commit()
215
- Stats.incr(f"edge_worker.heartbeat_count.{worker_name}", 1, 1)
216
- Stats.incr("edge_worker.heartbeat_count", 1, 1, tags={"worker_name": worker_name})
215
+ try:
216
+ from airflow.sdk._shared.observability.metrics.dual_stats_manager import DualStatsManager
217
+
218
+ DualStatsManager.incr(
219
+ "edge_worker.heartbeat_count",
220
+ 1,
221
+ 1,
222
+ tags={},
223
+ extra_tags={"worker_name": worker_name},
224
+ )
225
+ except ImportError:
226
+ from airflow.providers.common.compat.sdk import Stats
227
+
228
+ Stats.incr(f"edge_worker.heartbeat_count.{worker_name}", 1, 1)
229
+ Stats.incr("edge_worker.heartbeat_count", 1, 1, tags={"worker_name": worker_name})
217
230
  set_metrics(
218
231
  worker_name=worker_name,
219
232
  state=body.state,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: apache-airflow-providers-edge3
3
- Version: 2.0.0rc1
3
+ Version: 3.0.1rc1
4
4
  Summary: Provider package apache-airflow-providers-edge3 for Apache Airflow
5
5
  Keywords: airflow-provider,edge3,airflow,integration
6
6
  Author-email: Apache Software Foundation <dev@airflow.apache.org>
@@ -23,12 +23,14 @@ Classifier: Topic :: System :: Monitoring
23
23
  License-File: LICENSE
24
24
  License-File: NOTICE
25
25
  Requires-Dist: apache-airflow>=3.0.0,!=3.1.0
26
- Requires-Dist: apache-airflow-providers-common-compat>=1.10.1rc1
26
+ Requires-Dist: apache-airflow-providers-common-compat>=1.13.0rc1
27
27
  Requires-Dist: pydantic>=2.11.0
28
- Requires-Dist: retryhttp>=1.2.0,!=1.3.0
28
+ Requires-Dist: retryhttp>=1.4.0
29
+ Requires-Dist: aiofiles>=23.2.0
30
+ Requires-Dist: aiohttp>=3.9.2
29
31
  Project-URL: Bug Tracker, https://github.com/apache/airflow/issues
30
- Project-URL: Changelog, https://airflow.staged.apache.org/docs/apache-airflow-providers-edge3/2.0.0/changelog.html
31
- Project-URL: Documentation, https://airflow.staged.apache.org/docs/apache-airflow-providers-edge3/2.0.0
32
+ Project-URL: Changelog, https://airflow.staged.apache.org/docs/apache-airflow-providers-edge3/3.0.1/changelog.html
33
+ Project-URL: Documentation, https://airflow.staged.apache.org/docs/apache-airflow-providers-edge3/3.0.1
32
34
  Project-URL: Mastodon, https://fosstodon.org/@airflow
33
35
  Project-URL: Slack Chat, https://s.apache.org/airflow-slack
34
36
  Project-URL: Source Code, https://github.com/apache/airflow
@@ -59,7 +61,7 @@ Project-URL: YouTube, https://www.youtube.com/channel/UCSXwxpWZQ7XZ1WL3wqevChA/
59
61
 
60
62
  Package ``apache-airflow-providers-edge3``
61
63
 
62
- Release: ``2.0.0``
64
+ Release: ``3.0.1``
63
65
 
64
66
 
65
67
  Handle edge workers on remote sites via HTTP(s) connection and orchestrates work over distributed sites.
@@ -84,7 +86,7 @@ This is a provider package for ``edge3`` provider. All classes for this provider
84
86
  are in ``airflow.providers.edge3`` python package.
85
87
 
86
88
  You can find package information and changelog for the provider
87
- in the `documentation <https://airflow.apache.org/docs/apache-airflow-providers-edge3/2.0.0/>`_.
89
+ in the `documentation <https://airflow.apache.org/docs/apache-airflow-providers-edge3/3.0.1/>`_.
88
90
 
89
91
  Installation
90
92
  ------------
@@ -102,9 +104,11 @@ Requirements
102
104
  PIP package Version required
103
105
  ========================================== ===================
104
106
  ``apache-airflow`` ``>=3.0.0,!=3.1.0``
105
- ``apache-airflow-providers-common-compat`` ``>=1.10.1``
107
+ ``apache-airflow-providers-common-compat`` ``>=1.13.0``
106
108
  ``pydantic`` ``>=2.11.0``
107
- ``retryhttp`` ``>=1.2.0,!=1.3.0``
109
+ ``retryhttp`` ``>=1.4.0``
110
+ ``aiofiles`` ``>=23.2.0``
111
+ ``aiohttp`` ``>=3.9.2``
108
112
  ========================================== ===================
109
113
 
110
114
  Cross provider package dependencies
@@ -127,5 +131,5 @@ Dependent package
127
131
  ================================================================================================================== =================
128
132
 
129
133
  The changelog for the provider package can be found in the
130
- `changelog <https://airflow.apache.org/docs/apache-airflow-providers-edge3/2.0.0/changelog.html>`_.
134
+ `changelog <https://airflow.apache.org/docs/apache-airflow-providers-edge3/3.0.1/changelog.html>`_.
131
135
 
@@ -1,34 +1,33 @@
1
- airflow/providers/edge3/__init__.py,sha256=FoMZEvW444U8RrKOalwoiggPvVfyRqZ2Bgevcq48sC4,1492
2
- airflow/providers/edge3/get_provider_info.py,sha256=kVyhF2WJoGtSoG1XpUs0A-unstnAklNtdXpt3jkzRbA,7368
1
+ airflow/providers/edge3/__init__.py,sha256=Ua9vrlUHXeOcB6JPL3jXuCvWUeVCwBhnsGn4NdQkzVY,1492
2
+ airflow/providers/edge3/get_provider_info.py,sha256=GyA1KMmElIuPiRDI3dQLgaiSCctEMXP1XdT068g2k3I,7449
3
3
  airflow/providers/edge3/version_compat.py,sha256=mek4-fV-grwkP7F_kmRHKgZDfloTXi2ngS396UjjJUo,1577
4
4
  airflow/providers/edge3/cli/__init__.py,sha256=9hdXHABrVpkbpjZgUft39kOFL2xSGeG4GEua0Hmelus,785
5
- airflow/providers/edge3/cli/api_client.py,sha256=HyQ3fAQkrFkq9wdzQ4CgNDwYsnT9c_c48B8qkeD7LU8,7405
6
- airflow/providers/edge3/cli/dataclasses.py,sha256=JUuvvmzSVWvG9uOEfzLIiXrTZ-HbESvu50jkPpVIYVw,2895
7
- airflow/providers/edge3/cli/edge_command.py,sha256=aZ8P9x9FBR_pyuDxi6LaLkz4ubGOBDk1RNNp0ppTbKY,21747
5
+ airflow/providers/edge3/cli/api_client.py,sha256=24U_AUUWQs85lBD01u7F92mYo0Av_to8alxTfmJtIg0,7690
6
+ airflow/providers/edge3/cli/dataclasses.py,sha256=qTN47g9C22TwWVepgkFiQNR9Y_n1wMsTadjbtbhouVE,2594
7
+ airflow/providers/edge3/cli/definition.py,sha256=bXMrfhEf7xYlXxc4lTuVhQFYLRosd98PaN6eJNpRK9o,8707
8
+ airflow/providers/edge3/cli/edge_command.py,sha256=U9JpPV1a3jgM_im1jQ0fAI1KnU9Y9b72bLpeDIojH7w,16158
8
9
  airflow/providers/edge3/cli/signalling.py,sha256=sf4S6j6OoP0bLkda3UlCmlZabjv5wsMypy3kAvx56Z0,3220
9
- airflow/providers/edge3/cli/worker.py,sha256=il-17mwBpwuAhnB4BaqDvMfsZ1WwPwji8MCZ6lqvgPs,16727
10
+ airflow/providers/edge3/cli/worker.py,sha256=_c8VWTfNFRPv7zkyjQ42QodLLYJeyGJkIUU2A-fsHiU,18182
10
11
  airflow/providers/edge3/example_dags/__init__.py,sha256=9hdXHABrVpkbpjZgUft39kOFL2xSGeG4GEua0Hmelus,785
11
12
  airflow/providers/edge3/example_dags/integration_test.py,sha256=CTxHCy1Saaz_fdAilPkQ3nmeq1ScWdL9iUFdCkx-j4k,6281
12
- airflow/providers/edge3/example_dags/win_notepad.py,sha256=zYcrKqODN4KLZQ-5wNnZQQskrDd5LA-nKJNgKQDntSE,2832
13
+ airflow/providers/edge3/example_dags/win_notepad.py,sha256=DK-S8J3DOwmmEW44nFAYx5gFqLp8qGeew50jVm_labI,2822
13
14
  airflow/providers/edge3/example_dags/win_test.py,sha256=6kHelD1Uu8KfPJLdjHXrnC3SvnWEAKin-HdfVP3bh8o,13850
14
15
  airflow/providers/edge3/executors/__init__.py,sha256=y830gGSKCvjOcLwLuCDp84NCrHWWB9RSSH1qvJpFhyY,923
15
- airflow/providers/edge3/executors/edge_executor.py,sha256=MEl0FsciU6Yx7a9hbAAO_45NJNMSoF8z2fO2BB6ZbtM,17093
16
+ airflow/providers/edge3/executors/edge_executor.py,sha256=DM2FSDJs1BjK32ZIDLgUki2u9bKoIP0oWlhcNM08puE,16562
16
17
  airflow/providers/edge3/models/__init__.py,sha256=9hdXHABrVpkbpjZgUft39kOFL2xSGeG4GEua0Hmelus,785
17
- airflow/providers/edge3/models/edge_job.py,sha256=PQRZcrl8RCj9d8xvdNFit7UJ6zRxvME_gZBLyBTN_70,3621
18
+ airflow/providers/edge3/models/edge_job.py,sha256=TP0qNSVbTEjZQVbCij-hX1Enwq0dqqIX0uaNea02WZo,3579
18
19
  airflow/providers/edge3/models/edge_logs.py,sha256=rFVz4gR0GYiEpwai5Q2C5znkiuaUQTjq5EhfLnQUeZQ,3022
19
- airflow/providers/edge3/models/edge_worker.py,sha256=4xUh-4HIjSG5Sf-VBzsO6GwQUfT3BOGNOqEh5lltDDE,13869
20
+ airflow/providers/edge3/models/edge_worker.py,sha256=nnJcvvokYMniZxOQNx4Pl0cEy97NNwDFp6uRiz69woI,15193
20
21
  airflow/providers/edge3/plugins/__init__.py,sha256=9hdXHABrVpkbpjZgUft39kOFL2xSGeG4GEua0Hmelus,785
21
- airflow/providers/edge3/plugins/edge_executor_plugin.py,sha256=pzy66TGchlnMnQVy_v0DfYKanCtoUfEnmfRMcSGghmI,4887
22
- airflow/providers/edge3/plugins/templates/edge_worker_hosts.html,sha256=0_P2yfZwpy3Kvqd3GBvu_PgmmKCUbso3ieW8aYa76iU,8997
23
- airflow/providers/edge3/plugins/templates/edge_worker_jobs.html,sha256=bZ-6ysmIy6j4eR_TPHiqbgb3qpNMKCcEEB-SpxuxNgc,2831
22
+ airflow/providers/edge3/plugins/edge_executor_plugin.py,sha256=PkHWUOQOIfEoGS6DTa9KVNdIADDtIy4VuLK9SGP7YRI,4899
24
23
  airflow/providers/edge3/plugins/www/.gitignore,sha256=glCQO0xBUzFDPKNjn3_mw7F6e51j3sjyo4knJAUqMz4,281
25
24
  airflow/providers/edge3/plugins/www/.prettierignore,sha256=3FQ52dyPew57fO1lXEQTVRKfJClYQaM5tVkKWKSv4hg,56
26
25
  airflow/providers/edge3/plugins/www/.prettierrc,sha256=l0bDuMVuy86p4BwgAssF2AqJL6x_pZMSt8vm401QHyo,365
27
26
  airflow/providers/edge3/plugins/www/README.md,sha256=VLm9Gf_vSdATdAaSeHDkKHmw3Oo_r4ZIHyu_8o0hju4,5110
28
27
  airflow/providers/edge3/plugins/www/eslint.config.js,sha256=8KEosRBtZkvb2mZYWagAukze0WUu8hrPWz4eSj1ONKE,1851
29
28
  airflow/providers/edge3/plugins/www/index.html,sha256=PsqOtfHrJYYwQjxqcAkVOmsl2cRJe8biKygXJjAj2ng,413
30
- airflow/providers/edge3/plugins/www/package.json,sha256=nCoJ7F5ybPXPuFwY1uZUlhPRdW1iP6SLhKd2xhtPexk,2520
31
- airflow/providers/edge3/plugins/www/pnpm-lock.yaml,sha256=LsnLQxBd0YNVsDt0p2pmPgJXDkAjAQxvKfrwOWb5iBo,221704
29
+ airflow/providers/edge3/plugins/www/package.json,sha256=_GQtJRwY7b4q6YSas493EabPoTilbntPLM09Z8BU3-w,2710
30
+ airflow/providers/edge3/plugins/www/pnpm-lock.yaml,sha256=nOo507toNxCSTfoPBKwW8mSUt9_OJEZ6MhNF1QTQcEM,219401
32
31
  airflow/providers/edge3/plugins/www/testsSetup.ts,sha256=x1L_lXmigZgufra1L32Xcci_lLifbaG_tP6vx6gPscc,852
33
32
  airflow/providers/edge3/plugins/www/tsconfig.app.json,sha256=zpihgvrBvwjOwtHddJtYUi7Gp26diFtNYmJ7XlM3GUU,753
34
33
  airflow/providers/edge3/plugins/www/tsconfig.json,sha256=jZfUc2grkJB0eRDSFPEPfmBblsr__nGAww3ojidM0ho,158
@@ -36,7 +35,7 @@ airflow/providers/edge3/plugins/www/tsconfig.lib.json,sha256=Z5M3uhtIZ0Uc9CFjc7F
36
35
  airflow/providers/edge3/plugins/www/tsconfig.node.json,sha256=On9I0qUPqRSyxJNKP5OlnWX_rYR1CKZV8A3IgF1UxvE,680
37
36
  airflow/providers/edge3/plugins/www/vite.config.ts,sha256=mxAyXyZhIaFA46v7DY4yAo__y6gs9YXuIIPEhN-6xis,2971
38
37
  airflow/providers/edge3/plugins/www/dist/main.d.ts,sha256=eZKjnWzeXgUOt4RhqL-a2YYXWpSCboNcEQs5ZykL0kk,10
39
- airflow/providers/edge3/plugins/www/dist/main.umd.cjs,sha256=-1OZSMOxgfufuceeVkfDGs9R7haZ6S7SF6oWDtQS09Q,607654
38
+ airflow/providers/edge3/plugins/www/dist/main.umd.cjs,sha256=QCeiNGd32TXE7P6nosRs2iMxfPIavpYagphrKVdZCh4,637057
40
39
  airflow/providers/edge3/plugins/www/openapi-gen/queries/common.ts,sha256=8_JCD7ZPhld5Mkf8qVlMZC4Ai-T-KRsxbZe4vhA_Gj4,3780
41
40
  airflow/providers/edge3/plugins/www/openapi-gen/queries/ensureQueryData.ts,sha256=NVtfnBCRXCFppIh_7oPtwExL4n0xd3fCcFwVcsc9EMs,1612
42
41
  airflow/providers/edge3/plugins/www/openapi-gen/queries/index.ts,sha256=p941sYs7pyF4XLKPxPgBXIko0H6s2U4sowFygzJ6Jos,114
@@ -56,8 +55,9 @@ airflow/providers/edge3/plugins/www/openapi-gen/requests/core/OpenAPI.ts,sha256=
56
55
  airflow/providers/edge3/plugins/www/openapi-gen/requests/core/request.ts,sha256=jG833drJAZFBKN9hnEL6RIRmAfys9eb5rC8p99wBWXk,9598
57
56
  airflow/providers/edge3/plugins/www/src/constants.ts,sha256=431h7ZAwkQbZd4evYw7eGcEnj3z_PP2cPOtHTHb3GT0,1580
58
57
  airflow/providers/edge3/plugins/www/src/dev.tsx,sha256=5sZlduF3IFFXKZMxV06hLsxhcCuWNzUMM4Ni1RITG8w,1114
59
- airflow/providers/edge3/plugins/www/src/main.tsx,sha256=mY1QGUj7UNDq1H0AbG5lOK1Z3889iQrtPGOfwOBEb3A,1999
60
- airflow/providers/edge3/plugins/www/src/theme.ts,sha256=6Fbo0Mwbah6HTupBYyUqOt_T8DAZtDG2UABtOoxUe1w,21458
58
+ airflow/providers/edge3/plugins/www/src/global.d.ts,sha256=chLVHQJy1jR2szTg4c12GU2NF20SlGmf14bThSdm61Q,908
59
+ airflow/providers/edge3/plugins/www/src/main.tsx,sha256=jIba75vA0gIL3UND_ZYnRPwP9mX0ayLDJV2pz1_fge8,2253
60
+ airflow/providers/edge3/plugins/www/src/theme.ts,sha256=tl79j5JV9bw1VmSnNKrw7_2X5KGvpJ-3y06rjw0PKNo,21463
61
61
  airflow/providers/edge3/plugins/www/src/vite-env.d.ts,sha256=eY6SmeO3WS4Bxne5yY6kn_PXLilnlFfluNuZswLUDys,848
62
62
  airflow/providers/edge3/plugins/www/src/components/AddQueueButton.tsx,sha256=Ahyf0_NXqEM0UjIdMyTuANKToD1coqfEjdsQiudK_Fg,4159
63
63
  airflow/providers/edge3/plugins/www/src/components/ErrorAlert.tsx,sha256=4DFdnxEPWRBHCvMm5q5HKMH4D223jMNUX6zxKdZStNM,2182
@@ -89,7 +89,7 @@ airflow/providers/edge3/plugins/www/src/context/colorMode/ColorModeProvider.tsx,
89
89
  airflow/providers/edge3/plugins/www/src/context/colorMode/index.ts,sha256=nTdA6xva8PrXEybO-JdQN4oSY9GHlHCPvUwREzJvhDM,879
90
90
  airflow/providers/edge3/plugins/www/src/context/colorMode/useColorMode.tsx,sha256=YYcXELSveM_10fOwZeCh9yxiN8H7essKz1QDiy9Jio8,1122
91
91
  airflow/providers/edge3/plugins/www/src/layouts/EdgeLayout.tsx,sha256=17S8T1rnKA9416bz1yTeybK4_U_ENx2PbnezyN9PcXg,1532
92
- airflow/providers/edge3/plugins/www/src/layouts/NavTabs.tsx,sha256=BA1BHI6VAu_8uB3hkCtEhrvKjxoE5taPQUAI2_1UXHQ,2040
92
+ airflow/providers/edge3/plugins/www/src/layouts/NavTabs.tsx,sha256=1Uwki5aE9vIqJyZIukRzapbSYQNIMxq-nVDg0hBxkZw,2781
93
93
  airflow/providers/edge3/plugins/www/src/pages/JobsPage.tsx,sha256=tBgeEsd5TRDkwcsH2x3oOCMKyC4ak6GzfRbAZK6vjLI,4801
94
94
  airflow/providers/edge3/plugins/www/src/pages/WorkerPage.tsx,sha256=M8t8B5WfZHXRmTKYuVR1f3XIXG-QNIaw2EdCkZJUjpo,8403
95
95
  airflow/providers/edge3/plugins/www/src/res/README.md,sha256=v9BEjvcB_pOcCP0bCL8wZ00xovBdzSk79FPFlqM9ZoQ,1010
@@ -101,18 +101,18 @@ airflow/providers/edge3/plugins/www/src/utils/useContainerWidth.ts,sha256=lLNc0N
101
101
  airflow/providers/edge3/worker_api/__init__.py,sha256=nnPvxWGTEKZ9YyB1Yd7P9IvDOenK01LVHm22Owwxj3g,839
102
102
  airflow/providers/edge3/worker_api/app.py,sha256=yM2S2JLYE2lS4kN88XYnbeKKRa8vqVVhRq10yA_X0ig,3003
103
103
  airflow/providers/edge3/worker_api/auth.py,sha256=e6e9ZLIXP7qDwtsp_H2ZHEKpELsv7C8VZF6N_Qd68nI,4113
104
- airflow/providers/edge3/worker_api/datamodels.py,sha256=OsBalmLfAzrxEe66FZQI3yJ186tnTfg75yxVS0vtdfk,6674
104
+ airflow/providers/edge3/worker_api/datamodels.py,sha256=O8fVAwY2di7Fs_QfJ47FbE-5l9csbIte78updB1yU-g,7018
105
105
  airflow/providers/edge3/worker_api/datamodels_ui.py,sha256=yPEdtZ7noV5BBNXvA9F-pqVDq7UxTIKUdoUf3_FTDdE,2795
106
106
  airflow/providers/edge3/worker_api/v2-edge-generated.yaml,sha256=bcyJE_k2Mlc8Xn9bWSCG2A1ofhlpnvuz9LHWaMdRd_E,41191
107
107
  airflow/providers/edge3/worker_api/routes/__init__.py,sha256=9hdXHABrVpkbpjZgUft39kOFL2xSGeG4GEua0Hmelus,785
108
108
  airflow/providers/edge3/worker_api/routes/health.py,sha256=LTYvGxvs_OKcyEP6hFSw3J-bnBFP6soXmJlIKlkAyBI,1057
109
- airflow/providers/edge3/worker_api/routes/jobs.py,sha256=IXkVVnvdi46GlBTsS1CIzk6LzjZX1mfzXRCZqXiNuOg,5881
110
- airflow/providers/edge3/worker_api/routes/logs.py,sha256=k-5JYyl1n_G7Bi3iAOg6SG0bljr78_TaEWtY9X1y5Yc,5039
109
+ airflow/providers/edge3/worker_api/routes/jobs.py,sha256=YugykZO5IMu0YERxxO8WkD9vH-1xiZ1v_6XjcczxPg0,6459
110
+ airflow/providers/edge3/worker_api/routes/logs.py,sha256=PG4Ikj4YwHACGchT3g2xt09aLxMnwiUzRA80Jparyn8,5044
111
111
  airflow/providers/edge3/worker_api/routes/ui.py,sha256=dnlNZRUNw8WFMwL_oKKMAtu5vKlAeSQHTA_ko7n2raU,10491
112
- airflow/providers/edge3/worker_api/routes/worker.py,sha256=BqyKNe8U0X2GPDhAL5OmVAN5pC14yumbRCldBKL866g,9877
113
- apache_airflow_providers_edge3-2.0.0rc1.dist-info/entry_points.txt,sha256=7WUIGfd3o9NvvbK5trbZxNXTgYGc6pqg74wZPigbx5o,206
114
- apache_airflow_providers_edge3-2.0.0rc1.dist-info/licenses/LICENSE,sha256=gXPVwptPlW1TJ4HSuG5OMPg-a3h43OGMkZRR1rpwfJA,10850
115
- apache_airflow_providers_edge3-2.0.0rc1.dist-info/licenses/NOTICE,sha256=E3-_E02gwwSEFzeeWPKmnIjOoos3hW28CLISV6sYrbQ,168
116
- apache_airflow_providers_edge3-2.0.0rc1.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82
117
- apache_airflow_providers_edge3-2.0.0rc1.dist-info/METADATA,sha256=q-uIayP3RMPDGpwEZt99jqRzAo8bLgfNUordx7ywCFc,6141
118
- apache_airflow_providers_edge3-2.0.0rc1.dist-info/RECORD,,
112
+ airflow/providers/edge3/worker_api/routes/worker.py,sha256=K30GQ4FncuPe3q4NJVgLeL0V618zhONjwJa9e8-bfA4,10261
113
+ apache_airflow_providers_edge3-3.0.1rc1.dist-info/entry_points.txt,sha256=7WUIGfd3o9NvvbK5trbZxNXTgYGc6pqg74wZPigbx5o,206
114
+ apache_airflow_providers_edge3-3.0.1rc1.dist-info/licenses/LICENSE,sha256=gXPVwptPlW1TJ4HSuG5OMPg-a3h43OGMkZRR1rpwfJA,10850
115
+ apache_airflow_providers_edge3-3.0.1rc1.dist-info/licenses/NOTICE,sha256=_cWHznIoUSbLCY_KfmKqetlKlsoH0c2VBjmZjElAzuc,168
116
+ apache_airflow_providers_edge3-3.0.1rc1.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82
117
+ apache_airflow_providers_edge3-3.0.1rc1.dist-info/METADATA,sha256=Mh0_gOHiQ7JXyNdy0T3XNzyCtzz7lizw6qus-NC6zAc,6300
118
+ apache_airflow_providers_edge3-3.0.1rc1.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Apache Airflow
2
- Copyright 2016-2025 The Apache Software Foundation
2
+ Copyright 2016-2026 The Apache Software Foundation
3
3
 
4
4
  This product includes software developed at
5
5
  The Apache Software Foundation (http://www.apache.org/).
@@ -1,175 +0,0 @@
1
- {#
2
- Licensed to the Apache Software Foundation (ASF) under one
3
- or more contributor license agreements. See the NOTICE file
4
- distributed with this work for additional information
5
- regarding copyright ownership. The ASF licenses this file
6
- to you under the Apache License, Version 2.0 (the
7
- "License"); you may not use this file except in compliance
8
- with the License. You may obtain a copy of the License at
9
-
10
- http://www.apache.org/licenses/LICENSE-2.0
11
-
12
- Unless required by applicable law or agreed to in writing,
13
- software distributed under the License is distributed on an
14
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
- KIND, either express or implied. See the License for the
16
- specific language governing permissions and limitations
17
- under the License.
18
- #}
19
-
20
- {% extends base_template %}
21
-
22
- {% block title %}
23
- Edge Worker Hosts
24
- {% endblock %}
25
-
26
- {% block content %}
27
- <h2>Edge Worker Hosts</h2>
28
- {% if hosts|length == 0 %}
29
- <p>No Edge Workers connected or known currently.</p>
30
- {% else %}
31
-
32
- <script>
33
- function showForm(worker_name) {
34
- var button = document.getElementById("button_" + worker_name);
35
- var form = document.getElementById("form_" + worker_name);
36
- form.style.display = "block";
37
- button.style.display = "none";
38
- }
39
- function showEditComment(worker_name) {
40
- var display = document.getElementById("display_" + worker_name);
41
- var textarea = document.getElementById("textarea_" + worker_name);
42
- var button = document.getElementById("update_" + worker_name);
43
- display.style.display = "none";
44
- textarea.style.display = "block";
45
- button.style.display = "inline";
46
- }
47
- </script>
48
- <table class="table table-striped table-bordered">
49
- <tr>
50
- <th>Hostname</th>
51
- <th>State</th>
52
- <th>Queues</th>
53
- <th>First Online</th>
54
- <th>Last Heart Beat</th>
55
- <th>Active Jobs</th>
56
- <!-- Stats are not collected (yet) leave the columns out until available
57
- <th>Jobs Taken</th>
58
- <th>Jobs Success</th>
59
- <th>Jobs Failed</th>
60
- -->
61
- <th>System Information</th>
62
- <th>Operations</th>
63
- </tr>
64
- {% for host in hosts %}
65
- <tr>
66
- <td>{{ host.worker_name }}</a></td>
67
- <td>
68
- {%- if host.state in["offline", "offline maintenance"] -%}
69
- <span class="label" style="color:white; background-color:black;" title="Current State: {{ host.state }}">{{ host.state }}</span>
70
- {%- elif host.state == "unknown" -%}
71
- <span class="label" style="color:white; background-color:red;" title="Current State: {{ host.state }}">{{ host.state }}</span>
72
- {%- elif host.last_update.timestamp() <= five_min_ago.timestamp() -%}
73
- Reported <span class="label" style="color:white; background-color:red;" title="Current State: {{ host.state }}">{{ host.state }}</span>
74
- but no heartbeat
75
- {%- elif host.state in ["starting", "maintenance request", "maintenance exit"] -%}
76
- <span class="label" style="color:black; background-color:gold;" title="Current State: {{ host.state }}">{{ host.state }}</span>
77
- {%- elif host.state == "running" -%}
78
- <span class="label" style="color:white; background-color:green;" title="Current State: {{ host.state }}">{{ host.state }}</span>
79
- {%- elif host.state == "idle" -%}
80
- <span class="label" style="color:black; background-color:gray;" title="Current State: {{ host.state }}">{{ host.state }}</span>
81
- {%- elif host.state == "terminating" -%}
82
- <span class="label" style="color:black; background-color:violet;" title="Current State: {{ host.state }}">{{ host.state }}</span>
83
- {%- elif host.state in ["maintenance pending", "maintenance mode"] -%}
84
- <span class="label" style="color:black; background-color:orange;" title="Current State: {{ host.state }}">{{ host.state }}</span>
85
- {%- else -%}
86
- <span class="label" style="color:white; background-color:hotpink;" title="Current State: {{ host.state }}">{{ host.state }}</span>
87
- {%- endif -%}
88
- </td>
89
- <td>
90
- {% if host.queues %}
91
- <ul>
92
- {% for item in host.queues %}
93
- <li>
94
- <a href="../taskinstance/list/?_flt_7_state=success&_flt_7_state=failed&_flt_3_queue={{ item }}#"">{{ item }}</a>
95
- </li>
96
- {% endfor %}
97
- </ul>
98
- {% else %}
99
- (all)
100
- {% endif %}
101
- </td>
102
- <td><time datetime="{{ host.first_online }}">{{ host.first_online }}</time></td>
103
- <td>{% if host.last_update %}<time datetime="{{ host.last_update }}">{{ host.last_update }}</time>{% endif %}</td>
104
- <td>
105
- <a href="../taskinstance/list/?_flt_3_hostname={{ host.worker_name }}&_flt_7_state=success&_flt_7_state=failed#">{{ host.jobs_active }}</a>
106
- </td>
107
- <!-- Stats are not collected (yet) leave the columns out until available
108
- <td>{{ host.jobs_taken }}</td>
109
- <td>{{ host.jobs_success }}</td>
110
- <td>{{ host.jobs_failed }}</td>
111
- -->
112
- <td>
113
- <ul>
114
- {% for item in host.sysinfo_json %}
115
- <li>{{ item }}: {{ host.sysinfo_json[item] }}</li>
116
- {% endfor %}
117
- </ul>
118
- </td>
119
- {%- if host.state in ["idle", "running"] -%}
120
- <td>
121
- <button id="button_{{ host.worker_name }}" onclick="showForm('{{ host.worker_name }}')" class="btn btn-sm btn-primary">
122
- Enter Maintenance
123
- </button>
124
- <form id="form_{{ host.worker_name }}" style="display: none" action="../edgeworkerhosts/status/maintenance/{{ host.worker_name }}/on" method="POST">
125
- <input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
126
- <div style="white-space: pre-line;">
127
- <label for="maintenance_comment">Maintenance Comment:</label>
128
- </div>
129
- <textarea name="maintenance_comment" rows="3" maxlength="1024" style="width: 100%; margin-bottom: 5px;" required></textarea>
130
- <br />
131
- <button type="submit" class="btn btn-sm btn-primary">
132
- Confirm Maintenance
133
- </button>
134
- </td>
135
- </form>
136
- {%- elif host.state in ["maintenance pending", "maintenance mode", "maintenance request"] -%}
137
- <form action="../edgeworkerhosts/status/maintenance/{{ host.worker_name }}/off" method="POST">
138
- <td>
139
- <div id="display_{{ host.worker_name }}" style="white-space: pre-line;">
140
- {{ host.maintenance_comment }}
141
- <a onclick="showEditComment('{{ host.worker_name }}')" class="btn btn-sm btn-default" data-toggle="tooltip" rel="tooltip" title="Edit maintenance comment">
142
- <span class="sr-only">Edit</span>
143
- <i class="fa fa-edit"></i>
144
- </a>
145
- </div>
146
- <textarea id="textarea_{{ host.worker_name }}" name="maintenance_comment" rows="3" maxlength="1024" style="display: none; width:100%;" required>{{ host.maintenance_comment }}</textarea>
147
- <input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
148
- <div style="margin-top: 10px;">
149
- <button type="submit" class="btn btn-sm btn-primary">
150
- Exit Maintenance
151
- </button>
152
- <button id="update_{{ host.worker_name }}" type="submit" class="btn btn-sm btn-primary" style="display: none;" formaction="../edgeworkerhosts/status/maintenance/{{ host.worker_name }}/change_comment">
153
- Update comment
154
- </button>
155
- </div>
156
- </td>
157
- </form>
158
- {%- elif host.state in ["offline", "unknown", "offline maintenance"] -%}
159
- <form action="../edgeworkerhosts/status/maintenance/{{ host.worker_name }}/remove" method="POST">
160
- <td>
161
- <input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
162
- <button type="submit" class="btn btn-sm btn-primary">
163
- Remove
164
- </button>
165
- </td>
166
- </form>
167
- {%- else -%}
168
- <td></td>
169
- {% endif %}
170
- </tr>
171
- {% endfor %}
172
- </table>
173
- {% endif %}
174
- {% endblock %}
175
- <html>