Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds secret env_var #3048

Merged
merged 10 commits into from
Jan 23, 2025

Conversation

thomasjpfan
Copy link
Member

@thomasjpfan thomasjpfan commented Jan 10, 2025

Tracking issue

Related to flyteorg/flyte#6141 (comment)
Requires flyteorg/flyte#6160

Why are the changes needed?

This PR adds an env_var to the Secrets IDL, which has the follow behavior:

If mount_requirement is ENV_VAR, then we set an environment variable named env_name to the value of the secret.
If mount_requirement is FILE, then we set an environment variable named env_name to the path of the mounted secret.

What changes were proposed in this pull request?

This PR adds env_name to the Secrets IDL. This makes it easy to configure a secret in a Flyte task. For example, one can easily set a hugging face secret:

@task(secret_requests=[Secret(..., env_var="HF_TOKEN", mount_requirement=Secret.MountType.ENV_VAR)
def hello():
    ...

Or for secrets that require a file:

@task(secret_requests=[Secret(..., env_var="HF_TOKEN_PATH", mount_requirement=Secret.MountType.FILE)
def hello():
    ...

How was this patch tested?

I ran the following to try the two different modes:

from flytekit import task, Secret, ImageSpec
from typing import Optional
import os

image = ImageSpec(
    apt_packages=["git"],
    packages=[
        "git+https://github.com/thomasjpfan/flytekit.git@8814da92a8578dbad07550486a5aaced5785d7a5",
    ],
    registry="localhost:30000",
    commands=[
        "uv pip install git+https://github.com/thomasjpfan/flyte.git@25a7d9c100f571a9ce394e802d50ef8861eae7a4#subdirectory=flyteidl"
    ],
)



@task(
    container_image=image,
    secret_requests=[
        Secret(
            key="token",
            group="my-fun-group",
            mount_requirement=Secret.MountType.ENV_VAR,
            env_var="HELLO_WORLD",
        )
    ],
)
def get_secret_env_var() -> Optional[str]:
    return os.getenv("HELLO_WORLD")


@task(
    container_image=image,
    secret_requests=[
        Secret(
            key="token",
            group="my-fun-group",
            mount_requirement=Secret.MountType.FILE,
            env_var="HELLO_WORLD",
        )
    ],
)
def get_secret_file() -> str:
    with open(os.getenv("HELLO_WORLD"), "r") as f:
        return f.read()

Docs link

Summary by Bito

Enhanced Secret class in Flytekit implementing dual access methods (ENV_VAR and FILE) for secret management. Changes include renamed env_var parameter, improved functionality for direct secret value access, and core improvements to error handling. Added integration tests for Kubernetes secrets management with test fixtures and workflow demonstrations. This pull request also introduces an environment variable to the Secrets IDL, allowing secrets to be accessed as environment variables or file paths. It includes updates to integration tests for Kubernetes secrets with added checks for kubectl availability.

Unit tests added: True

Estimated effort to review (1-5, lower is better): 5

Signed-off-by: Thomas J. Fan <thomasjpfan@gmail.com>
@flyte-bot
Copy link
Contributor

flyte-bot commented Jan 10, 2025

Code Review Agent Run #f2a7e1

Actionable Suggestions - 0
Review Details
  • Files reviewed - 1 · Commit Range: 615499e..615499e
    • flytekit/models/security.py
  • Files skipped - 0
  • Tools
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ Successful

AI Code Review powered by Bito Logo

@flyte-bot
Copy link
Contributor

flyte-bot commented Jan 10, 2025

Changelist by Bito

This pull request implements the following key changes.

Key Change Files Impacted
Feature Improvement - Enhance Secret Class with env_var

security.py - Added env_var parameter to Secret class for flexible secret management.

Other Improvements - Update Dependency Version

pyproject.toml - Updated flyteidl dependency version from 1.14.1 to 1.14.2.

Testing - Add Integration Tests for Secret Management

test_remote.py - Introduced tests for Kubernetes secret management with fixtures and parametrized tests.

get_secret.py - Added new workflow tasks to test secret retrieval via environment variable and file.

Copy link

codecov bot commented Jan 10, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 83.58%. Comparing base (a86048a) to head (b2007d9).
Report is 6 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #3048      +/-   ##
==========================================
+ Coverage   77.44%   83.58%   +6.14%     
==========================================
  Files         238        3     -235     
  Lines       23158      195   -22963     
  Branches     2760        0    -2760     
==========================================
- Hits        17935      163   -17772     
+ Misses       4412       32    -4380     
+ Partials      811        0     -811     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@cosmicBboy
Copy link
Contributor

lgtm, tests will pass in this PR once this is merged right? flyteorg/flyte#6160

@thomasjpfan
Copy link
Member Author

lgtm, tests will pass in this PR once this is merged right? flyteorg/flyte#6160

Yea and when a new flyteidl version is released.

Signed-off-by: Thomas J. Fan <thomasjpfan@gmail.com>
@thomasjpfan thomasjpfan changed the title Adds secret env_name Adds secret env_var Jan 16, 2025
@flyte-bot
Copy link
Contributor

flyte-bot commented Jan 16, 2025

Code Review Agent Run #7c9e36

Actionable Suggestions - 0
Review Details
  • Files reviewed - 1 · Commit Range: 615499e..8814da9
    • flytekit/models/security.py
  • Files skipped - 0
  • Tools
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ Successful

AI Code Review powered by Bito Logo

…t_env_name

Signed-off-by: Thomas J. Fan <thomasjpfan@gmail.com>
Signed-off-by: Thomas J. Fan <thomasjpfan@gmail.com>
Signed-off-by: Thomas J. Fan <thomasjpfan@gmail.com>
@eapolinario
Copy link
Collaborator

Does it make sense to add an integration test (and leave it disabled while until we get a new Flyte sandbox version up)? At least you'll be able to validate that this works locally.

@flyte-bot
Copy link
Contributor

flyte-bot commented Jan 22, 2025

Code Review Agent Run #4296d4

Actionable Suggestions - 0
Additional Suggestions - 10
  • flytekit/exceptions/user.py - 1
    • Consider using classmethod for error code · Line 32-34
  • flytekit/remote/remote.py - 1
    • Consider consolidating duplicated signal handling logic · Line 635-721
  • plugins/flytekit-optuna/flytekitplugins/optuna/optimizer.py - 1
    • Consider simplifying validation logic conditions · Line 84-87
  • flytekit/core/worker_queue.py - 4
  • tests/flytekit/clis/sdk_in_container/test_serve.py - 2
    • Consider consistent CLI argument naming convention · Line 19-20
    • Consider more robust mocking approach · Line 14-14
  • flytekit/core/type_engine.py - 1
Review Details
  • Files reviewed - 48 · Commit Range: 8814da9..7e0bf7e
    • flytekit/bin/entrypoint.py
    • flytekit/clis/sdk_in_container/run.py
    • flytekit/clis/sdk_in_container/serve.py
    • flytekit/core/array_node_map_task.py
    • flytekit/core/context_manager.py
    • flytekit/core/node.py
    • flytekit/core/promise.py
    • flytekit/core/python_function_task.py
    • flytekit/core/type_engine.py
    • flytekit/core/worker_queue.py
    • flytekit/exceptions/user.py
    • flytekit/image_spec/default_builder.py
    • flytekit/image_spec/image_spec.py
    • flytekit/remote/remote.py
    • flytekit/tools/translator.py
    • plugins/flytekit-envd/flytekitplugins/envd/image_builder.py
    • plugins/flytekit-envd/tests/test_image_spec.py
    • plugins/flytekit-kf-pytorch/flytekitplugins/kfpytorch/task.py
    • plugins/flytekit-kf-pytorch/tests/test_elastic_task.py
    • plugins/flytekit-optuna/flytekitplugins/optuna/__init__.py
    • plugins/flytekit-optuna/flytekitplugins/optuna/optimizer.py
    • plugins/flytekit-optuna/setup.py
    • plugins/flytekit-optuna/tests/test_callback.py
    • plugins/flytekit-optuna/tests/test_decorator.py
    • plugins/flytekit-optuna/tests/test_imperative.py
    • plugins/flytekit-optuna/tests/test_optimizer.py
    • plugins/flytekit-optuna/tests/test_validation.py
    • plugins/flytekit-pydantic/flytekitplugins/pydantic/__init__.py
    • plugins/flytekit-pydantic/flytekitplugins/pydantic/basemodel_transformer.py
    • plugins/flytekit-pydantic/flytekitplugins/pydantic/commons.py
    • plugins/flytekit-pydantic/flytekitplugins/pydantic/deserialization.py
    • plugins/flytekit-pydantic/flytekitplugins/pydantic/serialization.py
    • plugins/flytekit-pydantic/setup.py
    • plugins/flytekit-pydantic/tests/folder/test_file1.txt
    • plugins/flytekit-pydantic/tests/folder/test_file2.txt
    • plugins/flytekit-pydantic/tests/test_type_transformer.py
    • pyproject.toml
    • tests/flytekit/clis/sdk_in_container/test_serve.py
    • tests/flytekit/integration/remote/test_remote.py
    • tests/flytekit/integration/remote/workflows/basic/signal_test.py
    • tests/flytekit/unit/bin/test_python_entrypoint.py
    • tests/flytekit/unit/core/image_spec/test_default_builder.py
    • tests/flytekit/unit/core/test_array_node_map_task.py
    • tests/flytekit/unit/core/test_type_engine.py
    • tests/flytekit/unit/core/test_type_hints.py
    • tests/flytekit/unit/core/test_worker_queue.py
    • tests/flytekit/unit/exceptions/test_user.py
    • tests/flytekit/unit/remote/test_remote.py
  • Files skipped - 2
    • plugins/flytekit-optuna/README.md - Reason: Filter setting
    • plugins/flytekit-pydantic/README.md - Reason: Filter setting
  • Tools
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ Successful

AI Code Review powered by Bito Logo

Signed-off-by: Thomas J. Fan <thomasjpfan@gmail.com>
Signed-off-by: Thomas J. Fan <thomasjpfan@gmail.com>
@thomasjpfan
Copy link
Member Author

Does it make sense to add an integration test (and leave it disabled while until we get a new Flyte sandbox version up)?

Added integration test in bc9b040 (Which is skipped now)

For it to be enabled, kubectl must be usable in the CI to create the secret.

@flyte-bot
Copy link
Contributor

flyte-bot commented Jan 22, 2025

Code Review Agent Run #7b0105

Actionable Suggestions - 3
  • tests/flytekit/integration/remote/workflows/basic/get_secret.py - 1
    • Consider adding error handling for secrets · Line 10-11
  • tests/flytekit/integration/remote/test_remote.py - 2
Review Details
  • Files reviewed - 2 · Commit Range: 7e0bf7e..27a0d3e
    • tests/flytekit/integration/remote/test_remote.py
    • tests/flytekit/integration/remote/workflows/basic/get_secret.py
  • Files skipped - 0
  • Tools
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ Successful

AI Code Review powered by Bito Logo

Comment on lines 10 to 11
def get_secret() -> str:
return current_context().secrets.get(group="my-group", key="token")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider adding error handling for secrets

Consider adding error handling around current_context().secrets.get() call to handle cases where the secret may not exist or be accessible.

Code suggestion
Check the AI-generated fix before applying
Suggested change
def get_secret() -> str:
return current_context().secrets.get(group="my-group", key="token")
def get_secret() -> str:
try:
return current_context().secrets.get(group="my-group", key="token")
except ValueError as e:
raise ValueError(f"Failed to retrieve secret: {str(e)}")

Code Review Run #7b0105


Is this a valid issue, or was it incorrectly flagged by the Agent?

  • it was incorrectly flagged

Comment on lines 908 to 928
subprocess.run([
"kubectl",
"create",
"secret",
"-n",
"flytesnacks-development",
"generic",
"my-group",
f"--from-literal=token={secret}",
], capture_output=True, text=True)
yield secret

# Remove secret
subprocess.run([
"kubectl",
"delete",
"secrets",
"-n",
"flytesnacks-development",
"my-group",
], capture_output=True, text=True)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add error handling for kubectl commands

Consider handling potential errors from subprocess.run() calls when creating and deleting the secret. The command could fail if kubectl is not installed or user lacks permissions.

Code suggestion
Check the AI-generated fix before applying
 @@ -908,11 +908,14 @@
     result = subprocess.run([
         "kubectl", 
         "create",
         "secret",
         "-n",
         "flytesnacks-development", 
         "generic",
         "my-group",
         f"--from-literal=token={secret}",
     ],  capture_output=True, text=True)
 +    if result.returncode != 0:
 +        raise RuntimeError(f"Failed to create secret: {result.stderr}")
     yield secret

     # Remove secret
     result = subprocess.run([
         "kubectl",
         "delete", 
         "secrets",
         "-n",
         "flytesnacks-development",
         "my-group",
     ],  capture_output=True, text=True)
 +    if result.returncode != 0:
 +        raise RuntimeError(f"Failed to delete secret: {result.stderr}")

Code Review Run #7b0105


Is this a valid issue, or was it incorrectly flagged by the Agent?

  • it was incorrectly flagged

Signed-off-by: Thomas J. Fan <thomasjpfan@gmail.com>
Signed-off-by: Thomas J. Fan <thomasjpfan@gmail.com>
@flyte-bot
Copy link
Contributor

flyte-bot commented Jan 23, 2025

Code Review Agent Run #aa41e1

Actionable Suggestions - 3
  • tests/flytekit/integration/remote/workflows/basic/get_secret.py - 3
    • Consider more descriptive env var names · Line 7-13
    • Consider adding env var error handling · Line 20-20
    • Consider adding error handling for file · Line 25-26
Review Details
  • Files reviewed - 2 · Commit Range: 27a0d3e..867bfd1
    • tests/flytekit/integration/remote/test_remote.py
    • tests/flytekit/integration/remote/workflows/basic/get_secret.py
  • Files skipped - 0
  • Tools
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ Successful

AI Code Review powered by Bito Logo

Signed-off-by: Thomas J. Fan <thomasjpfan@gmail.com>
@flyte-bot
Copy link
Contributor

flyte-bot commented Jan 23, 2025

Code Review Agent Run #dcba26

Actionable Suggestions - 0
Review Details
  • Files reviewed - 1 · Commit Range: 867bfd1..b2007d9
    • tests/flytekit/integration/remote/test_remote.py
  • Files skipped - 0
  • Tools
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ Successful

AI Code Review powered by Bito Logo

@thomasjpfan thomasjpfan merged commit f2a1742 into flyteorg:master Jan 23, 2025
106 of 108 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants