#GitHub - Infisical/infisical-dagger: Off...

1 messages ยท Page 1 of 1 (latest)

bleak sorrel
#
get name: input: module.withSource.initialize resolve: failed to initialize module: failed to call module "infisical" to get functions: call constructor: process "uv pip check" did not complete successfully: exit code: 1

Stderr:
Checked 37 packages in 2ms
Found 1 incompatibility
The package `main` requires `infisicalsdk>=0.2.0`, but it's not installed
#

They have a requirements.lock. I find that if I run dagger develop I get the following changed files:

infisical-dagger โžค git diff                                               git:main*
diff --git a/dagger.json b/dagger.json
index dfe783f..90a12cc 100644
--- a/dagger.json
+++ b/dagger.json
@@ -1,5 +1,6 @@
 {
   "name": "infisical",
   "sdk": "python",
-  "engineVersion": "v0.12.5"
+  "source": ".",
+  "engineVersion": "v0.13.0"
 }
diff --git a/requirements.lock b/requirements.lock
index 8127f3e..ef1a525 100644
--- a/requirements.lock
+++ b/requirements.lock
@@ -1,5 +1,7 @@
 # This file was autogenerated by uv via the following command:
-#    uv pip compile -o requirements.lock sdk/pyproject.toml pyproject.toml
+#    uv pip compile --universal -o requirements.lock sdk/pyproject.toml pyproject.toml
+aenum==3.1.15
+    # via infisicalsdk
 anyio==4.4.0
     # via
     #   dagger-io (sdk/pyproject.toml)
@@ -11,12 +13,22 @@ backoff==2.2.1
     # via gql
 beartype==0.18.5
     # via dagger-io (sdk/pyproject.toml)
+boto3==1.35.18
+    # via infisicalsdk
+botocore==1.35.18
+    # via
+    #   boto3
+    #   infisicalsdk
+    #   s3transfer
 cattrs==23.2.3
     # via dagger-io (sdk/pyproject.toml)
 certifi==2024.7.4
     # via
     #   httpcore
     #   httpx
+    #   requests
+charset-normalizer==3.3.2
+    # via requests
 deprecated==1.2.14
     # via
     #   opentelemetry-api
@@ -40,9 +52,16 @@ idna==3.7
     # via
     #   anyio
     #   httpx
+    #   requests
     #   yarl
 importlib-metadata==8.0.0
     # via opentelemetry-api
+infisicalsdk==0.2.0
+    # via main (pyproject.toml)
+jmespath==1.0.1
+    # via
+    #   boto3
+    #   botocore
 markdown-it-py==3.0.0
     # via rich
 mdurl==0.1.2
@@ -74,10 +93,22 @@ protobuf==4.25.4
     # via
     #   googleapis-common-protos
     #   opentelemetry-proto
+pydantic==1.10.18
+    # via infisicalsdk
 pygments==2.18.0
     # via rich
+python-dateutil==2.9.0.post0
+    # via
+    #   botocore
+    #   infisicalsdk
+requests==2.32.3
+    # via infisicalsdk
 rich==13.7.1
     # via dagger-io (sdk/pyproject.toml)
+s3transfer==0.10.2
+    # via boto3
+six==1.16.0
+    # via python-dateutil
 sniffio==1.3.1
     # via
     #   anyio
@@ -86,6 +117,12 @@ typing-extensions==4.12.2
     # via
     #   dagger-io (sdk/pyproject.toml)
     #   opentelemetry-sdk
+    #   pydantic
+urllib3==2.0.7
+    # via
+    #   botocore
+    #   infisicalsdk
+    #   requests
 wrapt==1.16.0
     # via deprecated
 yarl==1.9.4
silver bay
bleak sorrel
#

Ah, could be. Brain too full, got a link?

silver bay
#

I was seeing functions: call constructor: process "uv pip check" did not complete successfully: exit code: 1 from what Lev ran into but I think the real issue is The package main requires infisicalsdk>=0.2.0, but it's not installed and infisicalsdk needs to be in the requirements.txt

bleak sorrel
silver bay
#

Are you able to actually run the module locally?

#

and by locally i mean the one on github and not the one you ran develop on ๐Ÿ˜…

bleak sorrel
#

I can't publish the dagger develop'd one for another reason...License check? Which is working well, btw. Nice catch ๐Ÿ’ช

LICENSE license coverage too low ({Percent:67.35537190082644 Match:[{ID:MIT Type:Unknown Start:542 End:1565 IsURL:false}]})
fair rose
#

@bleak sorrel if you add the LICENSE file in the module source folder this also works

#

I've pushed a fixed yesterday to the Daggerverse that allows you to do this

thin abyss
#

Yeah this is the same issue

#

I fixed it with

In the main module I ran dagger develop and then cut a new release

In my project module that used the broken module I just pointed to the new version

bleak sorrel
# fair rose <@933501536624054272> if you add the LICENSE file in the module source folder t...

I don't think I can do that because the source attribute is the top level directory of the repo where the offending LICENSE file already lives.
This is a standalone reusable module, not a daggerized repo.

infisical-dagger โžค tree -L 2                                                                                        git:main
.
โ”œโ”€โ”€ LICENSE  << this one
โ”œโ”€โ”€ README.md
โ”œโ”€โ”€ dagger.json
โ”œโ”€โ”€ examples
โ”‚ย ย  โ””โ”€โ”€ get-secret-by-name
โ”œโ”€โ”€ pyproject.toml
โ”œโ”€โ”€ requirements.lock
โ”œโ”€โ”€ sdk
โ”‚ย ย  โ”œโ”€โ”€ LICENSE
โ”‚ย ย  โ”œโ”€โ”€ README.md
โ”‚ย ย  โ”œโ”€โ”€ codegen
โ”‚ย ย  โ”œโ”€โ”€ pyproject.toml
โ”‚ย ย  โ”œโ”€โ”€ src
โ”‚ย ย  โ””โ”€โ”€ uv.lock
โ””โ”€โ”€ src
    โ””โ”€โ”€ main
infisical-dagger โžค cat dagger.json                                                                                  git:main
{
  "name": "infisical",
  "sdk": "python",
  "source": ".",
  "engineVersion": "v0.13.0"
}
#

So I'll ask them to update from this

Copyright (c) 2022 Infisical Inc.

Portions of this software are licensed as follows:

- All content that resides under any "ee/" directory of this repository, if such directories exists, are licensed under the license defined in "ee/LICENSE".
- All third party components incorporated into the Infisical Software are licensed under the original license provided by the owner of the applicable component.
- Content outside of the above mentioned directories or restrictions above is available under the "MIT Expat" license as defined below.
...
<MIT license below>

to just MIT

bleak sorrel
#

To be fair on the old version...dagger functions didn't work because of missing infisicalsdk, so Daggerverse was right to reject.

bleak sorrel
#

Got things working. But I'm surprised that when we return a dagger.Secret on the command line we show the plaintext by default in the object print.

#

Seems like we should hide that unless someone invokes plaintext explicitly

#

surprised that my secret ends up being mongodb+srv://OVERRIDE_THIS:OVERRIDE_THIS@mongodb.net
When it seems like interpolation would give me: mongodb+srv://user1234:OVERRIDE_THIS@mongodb.net

bleak sorrel
#

๐Ÿ‘† that says

Modules run in Python 3.12 by default
The base image that runs Module Functions is now running Python 3.12 by default. If you need to go back to 3.11, either change requires-python = ">=3.11" in pyproject.toml, or create a .python-version file with 3.11 as the content.
but when I use uv lock I get

warning: `uv lock` is experimental and may change without warning
warning: No `requires-python` value found in the workspace. Defaulting to `>=3.11`.
#

src/main/__init__.py:6:8: F401 `dataclasses` imported but unused; consider removing, adding to `__all__`, or using a redundant alias
Found 1 error.
bleak sorrel
#

can't publish working module...

#

woah, turns out I needed another dagger develop after doing dagger develop; uv lock; rm requirements.lock with the python-requires in my pyproject.toml now set to >= 3.12:

uv.lock got changed during the dagger develop:

-[[distribution]]
+[[package]]
 name = "charset-normalizer"
 version = "3.3.2"
 source = { registry = "https://pypi.org/simple" }
@@ -123,7 +123,7 @@ wheels = [
     { url = "https://files.pythonhosted.org/packages/28/76/e6222113b83e3622caa4bb41032d0b1bf785250607392e1b778aca0b8a7d/charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc", size = 48543 },
 ]

-[[distribution]]
+[[package]]
 name = "dagger-io"
 version = "0.0.0"
 source = { editable = "sdk" }
@@ -139,7 +139,34 @@ dependencies = [
     { name = "typing-extensions" },
 ]

-[[distribution]]
+[package.metadata]
+requires-dist = [
+    { name = "anyio", specifier = ">=3.6.2" },
+    { name = "beartype", specifier = ">=0.18.2" },
...
#

Maybe that's what

warning: `uv lock` is experimental and may change without warning

means? Or part of us standardizing on uv?

#

Wait...I was trying to publish my main which is just a clone of the original. Will try to publish my branch.

void aurora
#

@bleak sorrel Just looking at this now to update my demonstration echo module. It looks like an access key is required, that a machine id/secret isn't sufficient alone to authenticate?

#

Haven't used Infisical in a while, getting secret not found on a secret that very much exists, key is correct, env slug is correct, project id is copied from project page, path is just /. This secret used to fetch fine before updating the sdk/auth, any of you Infisical users recall what else might have changed?

void aurora
bleak sorrel
#

btw, I'm just trying to help get this official Infisical one over the line vs my fork.

#

I haven't tried that example code yet either, just the CLI call, which worked for me.

#

Does something like

dagger call with-universal-auth --client-id=env:CLIENT_ID --client-secret=env:CLIENT_SECRET get-secret-by-name --project-id="<YOUR PROJ ID>" --secret-name="<YOUR SECRET NAME>" --environment-slug="dev" --secret-path="/"

work for you?

#

I just updated that test module as well to Dagger v0.13 and to use the infisical-dagger module in ../../.

void aurora
#

The Infisical call works, I'm hitting a Dagger issue with secrets as far as I can tell

#

Something to do with a secret originating from a dependency?

bleak sorrel
bleak sorrel
#

The infisical test works here

"""Returns a container that echoes whatever string argument is provided"""
        test_secret: Secret = (
            dag.infisical()
            .with_universal_auth(client_id, client_secret)
            .get_secret_by_name(
                project_id=project_id,
                environment_slug=environment_slug,
                secret_path="/",
                secret_name=secret_name,
            )
        )

        return await (
            dag.container()
            .from_("alpine:latest")
            .with_secret_variable("TEST", test_secret)
            .with_exec(["sh", "-c", 'echo "hello $TEST"'])
            .stdout()
        )
void aurora
#

So it's something specifically to do with storing a secret as an attribute of the function?

bleak sorrel
#

hmmm...
not sure

this works for me

import dagger
from dagger import dag, function, object_type

@object_type
class ReproSelfSecret:
    secret: dagger.Secret | None = None

    @function
    async def test(self, text: str) -> str:
        self.secret = dag.set_secret("mysecret", text)
        print(await self.secret.plaintext())
        return await self.secret.plaintext()
bleak sorrel
#

also good to get @full narwhal to take a look

bleak sorrel
#
import dagger
from dagger import dag, function, object_type


@object_type
class EchoMod:
    """This module will just echo a value from another module"""

    secret: dagger.Secret | None = None

    def container(self) -> dagger.Container:
        return dag.container().from_("alpine:latest")

    @function
    async def with_secret(
        self,
        auth_id: dagger.Secret,
        auth_secret: dagger.Secret,
        secret_name: str,
        project_id: str,
        env: str,
        secret_path: str = "/",
    ) -> "EchoMod":
        """Fetch a secret from Infisical"""
        inf_secret: dagger.Secret = (
            dag.infisical()
            .with_universal_auth(auth_id, auth_secret)
            .get_secret_by_name(
                project_id=project_id,
                environment_slug=env,
                secret_path=secret_path,
                secret_name=secret_name,
            )
        )
        print(await inf_secret.plaintext())
        self.secret = inf_secret
        return self

    @function
    async def echo(self, word: str = "Hello") -> dagger.Container:
        """Echo a provided 'word' or a secret fetched prior"""
        if self.secret is None:
            return self.container().with_exec(["echo", f"Here's a word... {word}"])

        return self.container().with_exec(
            ["echo", f"Here's a secret! {await self.secret.plaintext()}"]
        )
    
    @function
    async def with_secret_echo(
        self,
        auth_id: dagger.Secret,
        auth_secret: dagger.Secret,
        secret_name: str,
        project_id: str,
        env: str,
        secret_path: str = "/",
        word: str = "Hello",
    ) -> dagger.Container:
        await self.with_secret(auth_id, auth_secret, secret_name, project_id, env, secret_path)
        return await self.echo(word)
#

@void aurora I added a function called with_secret_echo at the bottom that allows everything to happen in one call. In this case, the state of the dagger.Secret in EchoMod is preserved and it works as you expect.

dagger call with-secret-echo --auth-id=env:CLIENT_ID --auth-secret=env:CLIENT_SECRET --secret-name=DATABASE_URL --project-id=653afc02eb2d2cbf91efbc0b --env=dev stdout
void aurora
#

This previously worked with a composition style, is that no longer supported or is this a temporary workaround until some issue is resolved with secrets?

bleak sorrel
#

@sand hedge @full narwhal ๐Ÿ‘† any ideas if something changed here

#

@void aurora is saying that he used to be able to call

dagger call with-secret --auth-id=env:CLIENT_ID --auth-secret=env:CLIENT_SECRET --secret-name=DATABASE_URL --project-id=653afc02eb2d2cbf91efbc0b --env=dev \
echo stdout
sand hedge
#

is the field private?

#

that can sometimes cause this particular issue. there's also a very weird caching one, that can happen if the SetSecret call gets cached

#

if you have a reproducable example, i can try it against my pr, it's definitely possible we have some more stuff lurking here

bleak sorrel
#

You can see the field here:

@object_type
class EchoMod:
    """This module will just echo a value from another module"""

    secret: dagger.Secret | None = None
#

in context above a bit in big code block

sand hedge
#

so i think that makes it private? if there's no field it's counted as "private" internally

#

if you add = field() that should hopefully work around the issue for now

bleak sorrel
#

trying that...

#

hmmm not sure how to do this with starting point

    secret: dagger.Secret | None = None

tried

    secret: dagger.Secret | None = field(None)
- TypeError: Module.field() takes 1 positional argument but 2 were given

will try

    secret: dagger.Secret = field(default=None)
- ValueError: Can't use a default value of None on a non-nullable type for
- parameter '{param.name}'

also tried

    secret: dagger.Secret = field(None)
- ValueError: Can't use a default value of None on a non-nullable type for
-    โ”ƒ parameter '{param.name}'

this hack finally worked @sand hedge @void aurora

+    secret: dagger.Secret = field(default=dag.set_secret("none", "none"))
#

There's an implicit connection today between field/getter function/public vs private field, which we'll want to make sure is clear and has all the cases covered. Thinking this note points to part of that near future state.
from: https://docs.dagger.io/manuals/developer/state-functions/

note
In a future version of the Python SDK, the dagger.function decorator will be used as a descriptor in place of dagger.field to make the distinction clearer.

Object state can be exposed as a Dagger Function, without having to create a getter function explicitly. Depending on the language used, this state is exposed using struct fields (Go), object attributes (Python) or object properties (TypeScript).

full narwhal
# bleak sorrel hmmm not sure how to do this with starting point ``` secret: dagger.Secret |...

The error messages are trying to help you ๐Ÿ™‚

secret: dagger.Secret | None = field(None)
- TypeError: Module.field() takes 1 positional argument but 2 were given

Solution: It's not a positional argument.

+dagger.field(default=...)

It's a common Python error that when you see one more positional argument in the error message than what you expect, that's because of self, which Python passes on automatically for instance methods.

Then you actually fixed it, but created another problem:

secret: dagger.Secret = field(default=None)
- ValueError: Can't use a default value of None on a non-nullable type for parameter '{param.name}'

Solution: Since the default is None, the type needs to allow None. Otherwise it's a "non-nullable" type!

+secret: dagger.Secret | None = dagger.field(default=None)

(bug: error message should end in ... type for parameter 'secret'! Fixed, pending push...)

void aurora
#

So dagger.field exposes the field to the user right, not planned but also not a problem so that's fine. Thanks all, that's the last thing (other than a run-through test!) on my to-do before demonstrating this on Thursday ๐Ÿ™‚

full narwhal
#

Yes, dagger.field() is a wrapper for dataclasses.field, to expose a getter function in Dagger for the attribute, and so it appears in the CLI as a function.