#Hi @Helder Correia @Jeremy Adams

1 messages · Page 1 of 1 (latest)

lusty plover
#

@mystic isle

chatGPT suggested this change

@object_type
class Infisical:
    infisical_client: InfisicalSDKClient = dataclasses.field(init=False)
    api_url: Annotated[
        dataclasses.InitVar[str],
        Doc("Your self-hosted Infisical site URL. Default: https://app.infisical.com."),
    ] = "https://app.infisical.com"

    def __post_init__(self, api_url: str = "https://app.infisical.com"):
        self.infisical_client = InfisicalSDKClient(host=api_url)

essentially giving an explicit default value for api_url in __post_init__

lusty plover
lusty plover
#

After making the change above, I get this error now:


✔ connect 0.9s
✔ initialize 1.2s
✔ prepare 0.0s
✔ setSecret(name: "92e708236d9a1b2ae8034b01a24880af4ccf51cb267db82643242e8665af890f"): Secret! 0.0s
✔ setSecret(name: "2713da821216077d2478edd14d5330d08bb6fb63371a2b452d565024e9cb5c06"): Secret! 0.0s
✘ infisical(apiUrl: "https://app.infisical.com"): Infisical! 2.2s
! call constructor: process "/runtime" did not complete successfully: exit code: 1
┃ ╭─ Error ──────────────────────────────────────────────────────────────────────╮                                                                                                         
┃ │ Failed to serialize result: Object of type InfisicalSDKClient is not JSON    │                                                                                                         
┃ │ serializable                                                                 │                                                                                                         
┃ ╰──────────────────────────────────────────────────────────────────────────────╯                                                                                                         

Error: response from query: input: infisical resolve: call constructor: process "/runtime" did not complete successfully: exit code: 1

Stderr:
╭─ Error ──────────────────────────────────────────────────────────────────────╮
│ Failed to serialize result: Object of type InfisicalSDKClient is not JSON    │
│ serializable                                                                 │
╰──────────────────────────────────────────────────────────────────────────────╯
#
@function
    def get_secret_by_name(
  ...
) -> dagger.Secret:
        """Get a secret by name"""
        secret = self.infisical_client.secrets.get_secret_by_name(
            secret_name=secret_name,
            project_id=project_id,
            environment_slug=environment_slug,
            secret_path=secret_path,
            expand_secret_references=expand_secret_references,
            include_imports=include_imports,
        )
        return dag.set_secret(secret_name, secret.secret.secret_value)
mystic isle
#

@lusty plover So does the private method instance also has to serializable, or does have some condition as like the arguments like only dagger or primitives methods?

#

The error is from InfisicalClient on method instance?

#

@lusty plover Also I think the default URL is not a good fix. The post init should had the value passed by dagger engine. The present one passed because even when not given its using default value. But I did pass in the argument of api_url as needed.

velvet wyvern
# mystic isle <@933501536624054272> So does the private method instance also has to serializa...

Each function in a chain runs in a separate container instance/run (different Python processes), and between those runs the object needs to be serialized and deserialized even on attributes that aren't exposed as Dagger Functions because they're still a part of the object's state. The Dagger engine needs to report to the next function in the chain what the current state of the object is so the next function initializes it before running its code. This also explains why you may see an issue only when chaining, because it's when that serialization/deserialization boundary is crossed.

@object_type is a wrapper around @dataclass, so the objects are serialized based on dataclasses.asdict. In this case, the InfisicalSDKClient object doesn't seem to be JSON serializable:

>>> import json
>>> from infisical_sdk import InfisicalSDKClient
>>> json.dumps(InfisicalSDKClient(host="https://app.infisical.com"))
TypeError: Object of type InfisicalSDKClient is not JSON serializable

That's ok though. It seems there's a few blindspots in the SDK that can be fixed, but may I suggest you do this instead:

@object_type
class Infisical:
    api_url: Annotated[
        str,
        Doc("Your self-hosted Infisical site URL. Default: https://app.infisical.com."),
    ] = "https://app.infisical.com"

    @cached_property
    def infisical_client(self) -> InfisicalSDKClient:
        return InfisicalSDKClient(host=self.api_url)

This way api_url is easily serialized although not exposed as a function, and self.infisical_client is ensured to be instantiated only once per Infisical instance, but without going through serialization.

lusty plover
#

@velvet wyvern thank you, yes I had issues even when I stripped things down quite a bit

import dataclasses
from typing import Annotated

import dagger
from dagger import Doc, dag, function, object_type
import infisical_sdk
from infisical_sdk import UniversalAuth, InfisicalSDKClient

@object_type
class Infisical:
    api_url: Annotated[
        dataclasses.InitVar[str],
        Doc("Your self-hosted Infisical site URL. Default: https://app.infisical.com."),
    ] = "https://app.infisical.com"
    client_id: Annotated[dagger.Secret, Doc("Your Machine Identity Client ID")]
    client_secret: Annotated[dagger.Secret, Doc("Your Machine Identity Client Secret.")]

    @function
    def universal_auth(
        self,
    ) -> str:
        """Authenticate with Universal Auth"""
        # client_id_dagger_secret = await self.client_id.plaintext()
        # client_secret_dagger_secret = await self.client_secret.plaintext()
        infisical_client =  InfisicalSDKClient(host=self.api_url)
        auth = UniversalAuth(infisical_client)
        tok = infisical_client.auth.universal_auth.login(
            client_id='<id>', client_secret='<token>'
        ).to_dict().get(key='accessToken')
        print(str(tok))
        return str(tok)
mystic isle
#

@velvet wyvern Understood. I am learning a lot on dagger now. It would be great if the team can design a more focused doc sections for developers who are implementing plugins.

May be my inexperience in python could be the reason. But it would be really great to work on it for easier understanding of dagger properties. I felt it needs a bit more organized.

#

One last doubt is to do chaining with sdk exposed?

Can i do with chaining with @cache_property or I cannot do it at all unless the SDK itself is JSON serializable?

mystic isle
#

Update @velvet wyvern Yes the @cached_property did the trick. Need to now check python doc on how to handle the singleton pattern, where we set the token internally.

velvet wyvern
velvet wyvern
# lusty plover <@768585883120173076> thank you, yes I had issues even when I stripped things do...

In this example, you'd need to remove the dataclasses.InitVar wrapper because it'll make it an init-only argument (constructor) and thus not available as an instance attribute at self.api_url. For more on this: https://docs.python.org/3/library/dataclasses.html#init-only-variables