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

WIP: fix(Backend+SDK): Update kubernetes.use_secret_as_volume to accept secret name dynamically at runtime #11039

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

DharmitD
Copy link
Contributor

@DharmitD DharmitD commented Jul 25, 2024

Description of your changes:
Resolves #10914

Attempting to pass the secret_name parameter in the dsl compile this way:

from kfp import dsl
from kfp import kubernetes

@dsl.component(base_image="python:3.10")
def print_secret():
    with open('/mnt/my_vol') as f:
        print(f.read())

@dsl.pipeline
def pipeline(secret_name: str = 'my-secret'):
    task = print_secret()
    kubernetes.use_secret_as_volume(task,
                                    secret_name=secret_name,
                                    mount_path='/mnt/my_vol')

results in this error:

File "/home/ddalvi/PycharmProjects/pythonProject2/main.py", line 23, in pipeline
    kubernetes.use_secret_as_volume(task,
  File "/home/ddalvi/miniconda3/envs/kfp_pipe_secret_env/lib/python3.11/site-packages/kfp/kubernetes/secret.py", line 81, in use_secret_as_volume
    secret_as_vol = pb.SecretAsVolume(
                    ^^^^^^^^^^^^^^^^^^
TypeError: bad argument type for built-in operation

The secret_name parameter was originally expected to be a string (str). However, in this case, it was being provided as a an object of the PipelineParameterChannel class , leading to a type mismatch error when the code tried to use it as a string.
Updated secret_name to accept either a str or PipelineParameterChannel using Union[str, PipelineParameterChannel] and added a check to convert PipelineParameterChannel to its string representation.

Furthermore,

  • Implemented support for dynamically specifying secret names in the use_secret_as_volume function.
  • Updated driver code to handle secret name substitution at runtime based on input parameters.
  • Introduced a {{secret_name}} template string representation for secret names in the compiled DSL.
  • Added a test to validate secret name template creation in IR.

Refer to this comment to understand why the driver code change is required.

Please refer to a PoC wherein we've listed out different test cases - four different pairs of DSL compile code and resulting pipeline yaml IRs with which we tested this update.

Collaborated with @gregsheremeta for this contribution, it was a joint effort. Thanks Greg for your contributions! :)

Checklist:

@gregsheremeta
Copy link
Contributor

/lgtm

I also verified it, so
/verified
:)

@chensun mind taking a quick look?

Copy link
Contributor

@diegolovison diegolovison left a comment

Choose a reason for hiding this comment

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

Please create a test for this scenario

Copy link
Contributor

@hbelmiro hbelmiro left a comment

Choose a reason for hiding this comment

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

/lgtm

@gregsheremeta
Copy link
Contributor

Please create a test for this scenario

good call

@DharmitD DharmitD force-pushed the secret_vol_params branch 7 times, most recently from c788e29 to e3b156b Compare August 1, 2024 04:14
Copy link
Contributor

@amadhusu amadhusu left a comment

Choose a reason for hiding this comment

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

Looks good to me !

@@ -147,6 +147,34 @@ def my_pipeline():
}
}

def test_with_secret_name_param(self):
@dsl.pipeline
def my_pipeline(secret_name: str = 'my-secret'):
Copy link
Contributor

Choose a reason for hiding this comment

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

It is missing a test that assert from the value my-secret

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The problem here is the pipeline spec generated from this compile step has the name stored in as a variable under the roots section.

root:
  dag:
    tasks:
      print-secret:
        cachingOptions:
          enableCache: true
        componentRef:
          name: comp-print-secret
        taskInfo:
          name: print-secret
  inputDefinitions:
    parameters:
      secret_name:
        defaultValue: my-secret
        isOptional: true
        parameterType: STRING
schemaVersion: 2.1.0
sdkVersion: kfp-2.8.0
---
platforms:
  kubernetes:
    deploymentSpec:
      executors:
        exec-print-secret:
          secretAsVolume:
          - mountPath: /mnt/my_vol
            optional: false
            secretName: secret_name

I tried a bunch of combinations to have the defaultValue field validated, so we know the name is being passed correctly, but the structure of this tests is such that if I pass in the entire pipelineSpec in the assert it fails:
https://github.com/kubeflow/pipelines/actions/runs/10191867165/job/28193820249#step:4:886

The tests only work when platform_spec is extracted and matched.

Note that the assert statement still verifies that the secret_name variable is getting passed into the secretAsVolume, I believe that's a good enough preliminary test at this point. Wdyt? @diegolovison @gregsheremeta

Copy link
Contributor

Choose a reason for hiding this comment

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

for posterity

The problem here is the pipeline spec generated from this compile step has the name stored in as a variable under the roots section.

we discovered today that that's not how this works. secretName (at the very bottom of the platforms spec) has to say secretName: my-secret and not secretName: secret_name

Copy link
Contributor

Choose a reason for hiding this comment

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

also for posterity, the above comment is also incorrect 😅

secretName: secret_name actually needs to be a key to the input parameter map, so we can grab the parameter by name at runtime. Newly added changes to driver.go show how we do that.

@DharmitD DharmitD marked this pull request as draft August 7, 2024 20:53
@DharmitD DharmitD changed the title fix(SDK): Update kubernetes.use_secret_as_volume to accept secret name as a parameter WIP: fix(SDK): Update kubernetes.use_secret_as_volume to accept secret name as a parameter Aug 7, 2024
Copy link

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: amadhusu
Once this PR has been reviewed and has the lgtm label, please assign chensun for approval. For more information see the Kubernetes Code Review Process.

The full list of commands accepted by this bot can be found here.

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@DharmitD DharmitD force-pushed the secret_vol_params branch 2 times, most recently from ad536ac to c83a482 Compare August 14, 2024 16:08
@DharmitD DharmitD marked this pull request as ready for review August 14, 2024 16:09
@DharmitD DharmitD changed the title WIP: fix(SDK): Update kubernetes.use_secret_as_volume to accept secret name as a parameter fix(SDK): Update kubernetes.use_secret_as_volume to accept secret name as a parameter Aug 14, 2024
@DharmitD DharmitD changed the title fix(SDK): Update kubernetes.use_secret_as_volume to accept secret name as a parameter fix(SDK): Update kubernetes.use_secret_as_volume to accept secret name dynamically at runtime Aug 14, 2024
@DharmitD
Copy link
Contributor Author

@chensun could you please take a look and let us know if this templating method looks good to you? Thanks!

@DharmitD
Copy link
Contributor Author

/rerun-all

@diegolovison
Copy link
Contributor

/lgtm

@DharmitD
Copy link
Contributor Author

DharmitD commented Aug 16, 2024

@chensun could you please take a look? Thanks!

- Implemented support for dynamically specifying secret names in the `use_secret_as_volume` function.
- Updated driver code to handle secret name substitution at runtime based on input parameters.
- Introduced a `{{my_secret}}` template string representation for secret names in the compiled DSL.
- Added a test to validate secret name template creation in IR.

Co-authored-by: Greg Sheremeta <[email protected]>
Signed-off-by: ddalvi <[email protected]>
Copy link

New changes are detected. LGTM label has been removed.

@google-oss-prow google-oss-prow bot removed the lgtm label Aug 19, 2024
@DharmitD
Copy link
Contributor Author

/rerun-all

@DharmitD
Copy link
Contributor Author

@chensun could you please take a look and let us know if this templating method looks good to you? Thanks!

@DharmitD
Copy link
Contributor Author

@chensun bumping :)

cc: @gregsheremeta @rimolive

# if secret_name is a PipelineParameterChannel, then we don't know what secret to mount until RUNTIME
# so, treat is as a map KEY instead of a secret name
if isinstance(secret_name, PipelineParameterChannel):
val = "{{" + secret_name.name + "}}"
Copy link
Collaborator

@HumairAK HumairAK Aug 28, 2024

Choose a reason for hiding this comment

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

I am uncertain about this approach, we're essentially implementing templating, but what maybe considered somewhat hacky. Have we considered other approaches?

For example, for names retrieved via parameterschannels, we can include a new field for SecretAsEnv called "secret_name_parameter".

Based on last community call @chensun had a proposal for an alternative approach as well, so I would be interested in hearing about this as well.

Copy link
Contributor

Choose a reason for hiding this comment

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

we can include a new field for SecretAsEnv called "secret_name_parameter".

that does feel cleaner to me

@HumairAK
Copy link
Collaborator

I've tested the implementation and it works as intended, however I think it's worth getting input from @chensun on the approach, I've left a comment here as well.


secretName := secretAsVolume.GetSecretName()

if strings.HasPrefix(secretName, "{{") && strings.HasSuffix(secretName, "}}") {
Copy link
Member

Choose a reason for hiding this comment

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

As discussed in the community meeting, we suggest follow the "inject inputs" pattern to accept dynamic runtime value.
Example PRs on "injecting inputs":
#10435
#5183

@DharmitD DharmitD changed the title fix(SDK): Update kubernetes.use_secret_as_volume to accept secret name dynamically at runtime WIP: fix(Backend+SDK): Update kubernetes.use_secret_as_volume to accept secret name dynamically at runtime Oct 9, 2024
@HumairAK HumairAK added this to the KFP SDK 2.11 milestone Oct 10, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
7 participants