Skip to content

Commit

Permalink
Merge branch 'master' into CDF-22368
Browse files Browse the repository at this point in the history
  • Loading branch information
VerstraeteBert authored Sep 2, 2024
2 parents ae17d04 + 95178fd commit 49b4c98
Show file tree
Hide file tree
Showing 14 changed files with 165 additions and 50 deletions.
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.6.2
rev: v0.6.3
hooks:
- id: ruff
args:
Expand Down
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,20 @@ Changes are grouped as follows
- `Fixed` for any bug fixes.
- `Security` in case of vulnerabilities.

## [7.55.2] - 2024-08-29
### Fixed
- Turn workflow_orchestration into data_workflows and add trigger doc, fix attribute names in data classes

## [7.55.1] - 2024-08-29
### Fixed
- Missing exports for workflow triggers

## [7.55.0] - 2024-08-23
### Added
- Support for creating a session using a one-shot token in the `client.iam.session.create` method.
- Parameter `nonce` to the `client.functions.call()` and `client.workflow.executions.run()` methods to allow passing
a custom nonce instead of letting the SDK generate it from your current credentials.

## [7.54.19] - 2024-08-23
### Added
- [Feature Preview - beta] Support for `client.workflows.triggers`.
Expand Down
7 changes: 6 additions & 1 deletion cognite/client/_api/functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -521,6 +521,7 @@ def call(
external_id: str | None = None,
data: dict | None = None,
wait: bool = True,
nonce: str | None = None,
) -> FunctionCall:
"""`Call a function by its ID or external ID. <https://developer.cognite.com/api#tag/Function-calls/operation/postFunctionsCall>`_.
Expand All @@ -529,6 +530,10 @@ def call(
external_id (str | None): External ID
data (dict | None): Input data to the function (JSON serializable). This data is passed deserialized into the function through one of the arguments called data. **WARNING:** Secrets or other confidential information should not be passed via this argument. There is a dedicated `secrets` argument in FunctionsAPI.create() for this purpose.'
wait (bool): Wait until the function call is finished. Defaults to True.
nonce (str | None): Nonce retrieved from sessions API when creating a session. This will be used to bind the session before executing the function. If not provided, a new session will be created based on the client credentials.
Tip:
You can create a session via the Sessions API, using the client.iam.session.create() method.
Returns:
FunctionCall: A function call object.
Expand All @@ -550,7 +555,7 @@ def call(
"""
identifier = IdentifierSequence.load(ids=id, external_ids=external_id).as_singleton()[0]
id = _get_function_internal_id(self._cognite_client, identifier)
nonce = create_session_and_return_nonce(self._cognite_client, api_name="Functions API")
nonce = nonce or create_session_and_return_nonce(self._cognite_client, api_name="Functions API")

if data is None:
data = {}
Expand Down
51 changes: 45 additions & 6 deletions cognite/client/_api/iam.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import warnings
from itertools import groupby
from operator import itemgetter
from typing import TYPE_CHECKING, Any, Dict, Iterable, Sequence, Union, overload
from typing import TYPE_CHECKING, Any, Dict, Iterable, Literal, Sequence, Union, overload

from typing_extensions import TypeAlias

Expand Down Expand Up @@ -34,7 +34,13 @@
SpaceIDScope,
UnknownAcl,
)
from cognite.client.data_classes.iam import GroupWrite, SecurityCategoryWrite, SessionStatus, TokenInspection
from cognite.client.data_classes.iam import (
GroupWrite,
SecurityCategoryWrite,
SessionStatus,
SessionType,
TokenInspection,
)
from cognite.client.utils._identifier import IdentifierSequence

if TYPE_CHECKING:
Expand Down Expand Up @@ -528,20 +534,53 @@ def __init__(self, config: ClientConfig, api_version: str | None, cognite_client
super().__init__(config, api_version, cognite_client)
self._LIST_LIMIT = 100

def create(self, client_credentials: ClientCredentials | None = None) -> CreatedSession:
def create(
self,
client_credentials: ClientCredentials | None = None,
session_type: SessionType | Literal["DEFAULT"] = "DEFAULT",
) -> CreatedSession:
"""`Create a session. <https://developer.cognite.com/api#tag/Sessions/operation/createSessions>`_
Args:
client_credentials (ClientCredentials | None): The client credentials to create the session. If set to None, a session will be created using the credentials used to instantiate -this- CogniteClient object. If that was done using a token, a session will be created using token exchange. Similarly, if the credentials were client credentials, a session will be created using client credentials. This method does not work when using client certificates (not supported server-side).
client_credentials (ClientCredentials | None): The client credentials to create the session. This is required
if session_type is set to 'CLIENT_CREDENTIALS'.
session_type (SessionType | Literal['DEFAULT']): The type of session to create. Can be
either 'CLIENT_CREDENTIALS', 'TOKEN_EXCHANGE', 'ONESHOT_TOKEN_EXCHANGE' or 'DEFAULT'.
Defaults to 'DEFAULT' which will use -this- CogniteClient object to create the session.
If this client was created using a token, 'TOKEN_EXCHANGE' will be used, and if
this client was created using client credentials, 'CLIENT_CREDENTIALS' will be used.
Session Types:
* **client_credentials**: Credentials for a session using client credentials from an identity provider.
* **token_exchange**: Credentials for a session using token exchange to reuse the user's credentials.
* **one_shot_token_exchange**: Credentials for a session using one-shot token exchange to reuse the user's credentials. One-shot sessions are short-lived sessions that are not refreshed and do not require support for token exchange from the identity provider.
Returns:
CreatedSession: The object with token inspection details.
"""
if client_credentials is None and isinstance((creds := self._config.credentials), OAuthClientCredentials):
if client_credentials is None and isinstance(creds := self._config.credentials, OAuthClientCredentials):
client_credentials = ClientCredentials(creds.client_id, creds.client_secret)

items = {"tokenExchange": True} if client_credentials is None else client_credentials.dump(camel_case=True)
session_type_up = session_type.upper()
if session_type_up == "DEFAULT": # For backwards compatibility after session_type was introduced
items = {"tokenExchange": True} if client_credentials is None else client_credentials.dump(camel_case=True)

elif session_type_up == "CLIENT_CREDENTIALS":
if client_credentials is None:
raise ValueError(
"For session_type='CLIENT_CREDENTIALS', either `client_credentials` must be provided OR "
"this client must be using OAuthClientCredentials"
)
items = client_credentials.dump(camel_case=True)

elif session_type_up == "TOKEN_EXCHANGE":
items = {"tokenExchange": True}

elif session_type_up == "ONESHOT_TOKEN_EXCHANGE":
items = {"oneshotTokenExchange": True}
else:
raise ValueError(f"Session type not understood: {session_type}")
return CreatedSession.load(self._post(self._RESOURCE_PATH, {"items": [items]}).json()["items"][0])

@overload
Expand Down
7 changes: 6 additions & 1 deletion cognite/client/_api/workflows.py
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,7 @@ def run(
input: dict | None = None,
metadata: dict | None = None,
client_credentials: ClientCredentials | None = None,
nonce: str | None = None,
) -> WorkflowExecution:
"""`Run a workflow execution. <https://api-docs.cognite.com/20230101/tag/Workflow-executions/operation/TriggerRunOfSpecificVersionOfWorkflow>`_
Expand All @@ -327,6 +328,7 @@ def run(
input (dict | None): The input to the workflow execution. This will be available for tasks that have specified it as an input with the string "${workflow.input}" See tip below for more information.
metadata (dict | None): Application specific metadata. Keys have a maximum length of 32 characters, values a maximum of 255, and there can be a maximum of 10 key-value pairs.
client_credentials (ClientCredentials | None): Specific credentials that should be used to trigger the workflow execution. When passed will take precedence over the current credentials.
nonce (str | None): The nonce to use to bind the session. If not provided, a new session will be created using the current credentials.
Tip:
The workflow input can be available in the workflow tasks. For example, if you have a Task with
Expand All @@ -339,6 +341,9 @@ def run(
... external_id="cdf_deployed_function:my_function",
... data={"workflow_data": "${workflow.input}",}))
Tip:
You can create a session via the Sessions API, using the client.iam.session.create() method.
Returns:
WorkflowExecution: The created workflow execution.
Expand All @@ -361,7 +366,7 @@ def run(
>>> credentials = ClientCredentials("my-client-id", os.environ["MY_CLIENT_SECRET"])
>>> res = client.workflows.executions.run("foo", "1", client_credentials=credentials)
"""
nonce = create_session_and_return_nonce(
nonce = nonce or create_session_and_return_nonce(
self._cognite_client, api_name="Workflow API", client_credentials=client_credentials
)
body = {"authentication": {"nonce": nonce}}
Expand Down
2 changes: 1 addition & 1 deletion cognite/client/_version.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from __future__ import annotations

__version__ = "7.54.19"
__version__ = "7.55.2"
__api_subversion__ = "20230101"
11 changes: 11 additions & 0 deletions cognite/client/data_classes/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,11 @@
WorkflowList,
WorkflowTask,
WorkflowTaskExecution,
WorkflowTrigger,
WorkflowTriggerCreate,
WorkflowTriggerList,
WorkflowTriggerRun,
WorkflowTriggerRunList,
WorkflowUpsert,
WorkflowUpsertList,
WorkflowVersion,
Expand Down Expand Up @@ -569,6 +574,12 @@
"WorkflowTask",
"WorkflowUpsertList",
"WorkflowVersionUpsertList",
"WorkflowVersionUpsertList",
"WorkflowTrigger",
"WorkflowTriggerCreate",
"WorkflowTriggerList",
"WorkflowTriggerRun",
"WorkflowTriggerRunList",
"HasName",
"HasExternalId",
"HasInternalId",
Expand Down
29 changes: 21 additions & 8 deletions cognite/client/data_classes/workflows.py
Original file line number Diff line number Diff line change
Expand Up @@ -1413,34 +1413,47 @@ class WorkflowTriggerRun(CogniteResource):

def __init__(
self,
trigger_external_id: str,
trigger_fire_time: int,
external_id: str,
fire_time: int,
workflow_external_id: str,
workflow_version: str,
workflow_execution_id: str,
status: Literal["success", "failed"],
reason_for_failure: str | None = None,
) -> None:
self.trigger_external_id = trigger_external_id
self.trigger_fire_time = trigger_fire_time
self.external_id = external_id
self.fire_time = fire_time
self.workflow_external_id = workflow_external_id
self.workflow_version = workflow_version
self.workflow_execution_id = workflow_execution_id
self.status = status
self.reason_for_failure = reason_for_failure

def dump(self, camel_case: bool = True) -> dict[str, Any]:
item = {
"trigger_external_id": self.trigger_external_id,
"trigger_fire_time": self.trigger_fire_time,
"external_id": self.external_id,
"fire_time": self.fire_time,
"workflow_external_id": self.workflow_external_id,
"workflow_version": self.workflow_version,
"workflow_execution_id": self.workflow_execution_id,
"status": self.status,
}
if self.reason_for_failure:
item["reason_for_failure"] = self.reason_for_failure
if camel_case:
return convert_all_keys_to_camel_case(item)
return item

@classmethod
def _load(cls, resource: dict, cognite_client: CogniteClient | None = None) -> WorkflowTriggerRun:
return cls(
trigger_external_id=resource["triggerExternalId"],
trigger_fire_time=resource["triggerFireTime"],
external_id=resource["externalId"],
fire_time=resource["fireTime"],
workflow_external_id=resource["workflowExternalId"],
workflow_version=resource["workflowVersion"],
workflow_execution_id=resource["workflowExecutionId"],
status=resource["status"],
reason_for_failure=resource.get("reasonForFailure"),
)


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,23 @@ Update Status of Async Task
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. automethod:: cognite.client._api.workflows.WorkflowTaskAPI.update

Workflow Triggers
-------------------
Create triggers for workflow executions
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. automethod:: cognite.client._api.workflows.WorkflowTriggerAPI.create

Delete triggers for workflow executions
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. automethod:: cognite.client._api.workflows.WorkflowTriggerAPI.delete

Get triggers for workflow executions
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. automethod:: cognite.client._api.workflows.WorkflowTriggerAPI.get_triggers

Get trigger run history for a workflow trigger
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. automethod:: cognite.client._api.workflows.WorkflowTriggerAPI.get_trigger_run_history

Data Workflows data classes
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
2 changes: 1 addition & 1 deletion docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ Contents
data_organization
transformations
functions
workflow_orchestration
data_workflows
unit_catalog
filters
deprecated
Expand Down
Loading

0 comments on commit 49b4c98

Please sign in to comment.