Heya! Trying to make a flow that does some GraphQ...
# prefect-community
m
Heya! Trying to make a flow that does some GraphQL stuff - specifically, turning off schedules (via
set_schedule_inactive
). It lets me read (I grab all the flows from a given project), but the
mutate
gives me this error (the query works when I go to the Interactive tab on the GUI btw)
Copy code
AuthorizationError([{'path': ['flow'], 'message': 'AuthenticationError: Forbidden', 'extensions': {'code': 'UNAUTHENTICATED'}}])
Aha! I was trying to generate them and map them, but I guess you can only have 1 client object at a time.
Hrm, so it worked when I ran it locally in Jupyter, but when I registered it and run it from the Prefect GUI it says this now
Unexpected error: ClientError([{'path': ['set_schedule_inactive'], 'message': 'Unauthorized', 'extensions': {'code': 'FORBIDDEN'}}])
k
What!? I can’t see why it would throw this. Could you give me a code snippet? What type of agent are you using?
a
Anecdotally, I came across a similar error on my agent when I deleted old API keys 🙂 Can you try generating a new API key in your Prefect Cloud UI and try authenticating again? You can also supply the API key directly to your agent e.g.
Copy code
prefect agent local start --label xxx --key API_KEY
m
@Kevin Kho Using the Fargate Agent (we're still on 0.13.19 - I know, I know lol. We'll upgrade as soon as this PR gets merged, I promise! https://github.com/PrefectHQ/prefect/pull/5411) so we grab IDs with these two (this works!)
Copy code
@task
def make_project_flow_grabber_stmt(project: str) -> str:
    return "\n".join(
        [
            "{",
            "  flow(",
            f'    where: {{_and: [{{archived: {{_eq: false}}}}, {{project: {{name: {{_eq: "{project}"}}}}}}]}}',
            "  ) {",
            "    id",
            "  }",
            "}",
        ]
    )


@task(log_stdout=True, max_retries=3, retry_delay=datetime.timedelta(seconds=10))
def run_graphql(query: str):
    logger = prefect.context.get("logger")
    <http://logger.info|logger.info>(query)
    client = Client()
    return client.graphql(query)
then try to turn off the schedules in that project with this:
Copy code
@task
def make_flow_inactive_queries(flow_ids: t.List[str]) -> t.List[str]:
    return [
        "\n".join(
            [
                "mutation {",
                "  set_schedule_inactive(input: {",
                f"""    flow_id: "{flow_id['id']}" """,
                "  }) {",
                "    success",
                "  }",
                "}",
            ]
        )
        for flow_id in flow_ids
    ]


@task
def turn_off_schedules(queries: t.List[str]) -> t.List[dict]:
    client = Client()
    return [client.graphql(query) for query in queries]
and here's the body of the flow itself:
Copy code
project = Parameter("project", required=True, default="")
    flow_query = make_project_flow_grabber_stmt(project)
    query_result = run_graphql(flow_query)
    queries = make_flow_inactive_queries(query_result["data"]["flow"])
    mutated = turn_off_schedules(queries)
@Anna Geller I did try making a new Service Account with Administrator Privileges, then I passed an API key from that to the
Client
object. Didn't work - is that sorta the same thing?
k
You know what? I think it’s related to an old API key potentially not having permissions for that route. Could you try a key from here ? Not super sure
It might be the API key of your agent that makes the call?
m
@Kevin Kho Tried making a new API key from the link you posted, saving it as a Secret, then passing it to the Flow. Didn't work, but it did give a new error message!
prefect.utilities.exceptions.AuthorizationError: [{'path': ['set_schedule_inactive'], 'message': 'AuthenticationError: Forbidden', 'extensions': {'code': 'UNAUTHENTICATED'}}]
This is the code btw:
Copy code
@task
def turn_off_schedules(queries: t.List[str]) -> t.List[dict]:
    api_key = PrefectSecret("MATT_API_KEY")
    client = Client(api_token=api_key)
    return [client.graphql(query) for query in queries]
k
Just wanna be clear. You are running a Flow that calls the Client and then sets the schedule as inactive during a Flow Run?
m
@Kevin Kho Right, for a bunch of other flows. Making some "staging" Projects where people can test out flows before pushing them to Prod - buuut if they have a Schedule attached, we don't want like a bunch of versions of every flow to run. So it takes a Project (like the "Matt" project), then deactivates every Schedule on every Flow in it.
k
Wait though, you can’t use PrefectSecret in a task right? Can you try changing to
Secret.get()
?
m
Aha! Just changed it to
Copy code
@task
def turn_off_schedules(queries: t.List[str], api_key) -> t.List[dict]:
    client = Client(api_token=api_key)
    return [client.graphql(query) for query in queries]
k
Does that work now?
m
@Kevin Kho Woohoo! Worked! Thanks!
(after a few rounds of fat-fingering a key, editing the flow directly in GitHub like a maniac, then watching it die in CI/CD 😅 )
k
Finally lol
💯 1