This repository has been archived by the owner on Apr 26, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #19 from PrefectHQ/job-tasks
adds `job` tasks
- Loading branch information
Showing
15 changed files
with
684 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -135,4 +135,4 @@ dmypy.json | |
.vscode | ||
|
||
# Jupyter notebook | ||
*.ipynb | ||
*.ipynb |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
::: prefect_kubernetes.credentials |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
::: prefect_kubernetes.exceptions |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
::: prefect_kubernetes.jobs |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -37,3 +37,5 @@ plugins: | |
nav: | ||
- Home: index.md | ||
- Credentials: credentials.md | ||
- Exceptions: exceptions.md | ||
- Jobs: jobs.md |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
"""Module for defining Kubernetes credential handling and client generation.""" | ||
|
||
from contextlib import contextmanager | ||
from typing import Generator, Optional | ||
|
||
from kubernetes import config as kube_config | ||
from kubernetes.client import ApiClient, AppsV1Api, BatchV1Api, CoreV1Api | ||
from kubernetes.config.config_exception import ConfigException | ||
from prefect.blocks.core import Block | ||
from prefect.blocks.kubernetes import KubernetesClusterConfig | ||
|
||
|
||
class KubernetesCredentials(Block): | ||
"""Credentials block for generating configured Kubernetes API clients. | ||
Attributes: | ||
cluster_config: A `KubernetesClusterConfig` block holding a JSON kube | ||
config for a specific kubernetes context. | ||
Examples: | ||
Load stored Kubernetes credentials: | ||
```python | ||
from prefect_kubernetes.credentials import KubernetesCredentials | ||
kubernetes_credentials = KubernetesCredentials.load("my-k8s-credentials") | ||
``` | ||
Create resource-specific API clients from KubernetesCredentials: | ||
```python | ||
from prefect_kubernetes import KubernetesCredentials | ||
kubernetes_credentials = KubernetesCredentials.load("my-k8s-credentials") | ||
kubernetes_app_v1_client = kubernetes_credentials.get_app_client() | ||
kubernetes_batch_v1_client = kubernetes_credentials.get_batch_client() | ||
kubernetes_core_v1_client = kubernetes_credentials.get_core_client() | ||
``` | ||
Create a namespaced job: | ||
```python | ||
from prefect import flow | ||
from prefect_kubernetes import KubernetesCredentials | ||
from prefect_kubernetes.job import create_namespaced_job | ||
from kubernetes.client.models import V1Job | ||
kubernetes_credentials = KubernetesCredentials.load("my-k8s-credentials") | ||
@flow | ||
def kubernetes_orchestrator(): | ||
create_namespaced_job( | ||
body=V1Job(**{"Marvin": "42"}), | ||
kubernetes_credentials=kubernetes_credentials | ||
) | ||
``` | ||
""" | ||
|
||
_block_type_name = "Kubernetes Credentials" | ||
_logo_url = "https://images.ctfassets.net/zscdif0zqppk/oYuHjIbc26oilfQSEMjRv/a61f5f6ef406eead2df5231835b4c4c2/logo.png?h=250" # noqa | ||
|
||
cluster_config: Optional[KubernetesClusterConfig] = None | ||
|
||
@contextmanager | ||
def get_app_client(self) -> Generator[AppsV1Api, None, None]: | ||
"""Convenience method for retrieving a Kubernetes API client for deployment resources. | ||
Yields: | ||
Kubernetes API client to interact with "deployment" resources. | ||
""" | ||
with self.get_generic_client() as generic_client: | ||
try: | ||
yield AppsV1Api(api_client=generic_client) | ||
finally: | ||
generic_client.rest_client.pool_manager.clear() | ||
|
||
@contextmanager | ||
def get_batch_client(self) -> Generator[BatchV1Api, None, None]: | ||
"""Convenience method for retrieving a Kubernetes API client for job resources. | ||
Yields: | ||
Kubernetes API client to interact with "job" resources. | ||
""" | ||
with self.get_generic_client() as generic_client: | ||
try: | ||
yield BatchV1Api(api_client=generic_client) | ||
finally: | ||
generic_client.rest_client.pool_manager.clear() | ||
|
||
@contextmanager | ||
def get_core_client(self) -> Generator[CoreV1Api, None, None]: | ||
"""Convenience method for retrieving a Kubernetes API client for core resources. | ||
Yields: | ||
Kubernetes API client to interact with "pod", "service" | ||
and "secret" resources. | ||
""" | ||
with self.get_generic_client() as generic_client: | ||
try: | ||
yield CoreV1Api(api_client=generic_client) | ||
finally: | ||
generic_client.rest_client.pool_manager.clear() | ||
|
||
def get_generic_client(self) -> ApiClient: | ||
""" | ||
Utility function for configuring a generic Kubernetes client. | ||
It will attempt to connect to a Kubernetes cluster in three steps with | ||
the first successful connection attempt becoming the mode of communication with | ||
a cluster: | ||
1. It will first attempt to use a `KubernetesCredentials` block's | ||
`cluster_config` to configure a client using | ||
`KubernetesClusterConfig.configure_client`. | ||
2. Attempt in-cluster connection (will only work when running on a pod). | ||
3. Attempt out-of-cluster connection using the default location for a | ||
kube config file. | ||
Returns: | ||
An authenticated, generic Kubernetes Client. | ||
""" | ||
|
||
if self.cluster_config: | ||
self.cluster_config.configure_client() | ||
else: | ||
try: | ||
kube_config.load_incluster_config() | ||
except ConfigException: | ||
kube_config.load_kube_config() | ||
|
||
client = ApiClient() | ||
return client |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
"""Module to define common exceptions within `prefect_kubernetes`.""" | ||
|
||
from kubernetes.client.exceptions import ApiException, OpenApiException | ||
|
||
|
||
class KubernetesJobDefinitionError(OpenApiException): | ||
"""An exception for when a Kubernetes job definition is invalid.""" | ||
|
||
|
||
class KubernetesJobFailedError(OpenApiException): | ||
"""An exception for when a Kubernetes job fails.""" | ||
|
||
|
||
class KubernetesResourceNotFoundError(ApiException): | ||
"""An exception for when a Kubernetes resource cannot be found by a client.""" |
Oops, something went wrong.