Hi! I am using the prefect REST API to create pre...
# ask-community
j
Hi! I am using the prefect REST API to create prefect_aws blocks. I successfully created a aws-credentials block, but when I try to create a s3-bucket block (in prefect cloud, here it is the official doc), I don't know how to relate the previous block for credentials. I tried to relate the block manually in the web UI. Then, if I get the block using the API for the s3-bucket block I see the plain credentials (aws_access_key_id, aws_secret_access_key, ...). How can I reference the aws-credentials block to the s3-bucket block? Thank you!
n
hi @jcozar - happy to help if you can share what you've tried / what part (in terms of your http client or whatever you're using) you're stuck at
if you're using the REST api you'll need to use the JSON serialized representation of the block, so using the client to read block documents might be a good reference
j
Hi @Nate, of course! I created a aws-credential block and s3-bucket block like this:
Copy code
base_url = f"<https://api.prefect.cloud/api/accounts/{prefect_secrets['PREFECT_ACCOUNT_ID']}/workspaces/{prefect_secrets['PREFECT_WORKSPACE_ID']}>"

    # Authorization headers
    headers = {
        "Authorization": f"Bearer {prefect_secrets['PREFECT_API_KEY']}",
        "Content-Type": "application/json"
    }

# Create aws credentials block
slug = "aws-credentials"
# created on 2022-11-16T17:43:57.765962Z
block_type_id = "2b9baa6c-86df-4019-9711-392fb5b937d9"
    
# created on 2025-01-16T17:28:06.240831Z
block_schema_id = "6674cc7d-3545-4cdf-9a12-eab2199f22c2"
    
# build data
credentials_name = "mycredentials"
access_key_id = "..."
secret_access_key = "..."
name = "mycredentials"
data = {
    "aws_access_key_id": access_key_id,
    "aws_secret_access_key": secret_access_key,
    "region_name": "eu-west1",
}

url = f"{base_url}/block_documents"
response = requests.post(url, headers=headers, json={
    "name": name,
    "block_type_id": block_type_id,
    "block_schema_id": block_schema_id,
    "data": data
})
block_credentials_id = response.json()["id"]

# Create s3-bucket block
slug = "s3-bucket"
# created on 2023-02-19T09:16:43.906341Z
block_type_id = "e7ef6d0d-d49b-4e8d-970c-a2e66b35a872"

# created on 2025-01-16T17:38:14.090658Z
block_schema_id = "8e52f2cb-4385-4cef-9652-c3bf16bf1f5a"

# build data
name = "mybucket"
data = {
    "bucket_name": "mybucket",
    "credentials": block_credentials_id
}
url = f"{base_url}/block_documents"
response = requests.post(url, headers=headers, json={
    "name": name,
    "block_type_id": block_type_id,
    "block_schema_id": block_schema_id,
    "data": data
})
It works correctly, except that the block mybucket is created with none credentials, like it is shown in the snapshot
If I edit manually in the UI the mybucket block and I add the reference to the previous aws-credentials block it works like in the picture
If I use the REST API (link) to get the mybucket block detals (/block_types/slug/{slug}/block_documents/name/{block_document_name}), the response is like this:
Copy code
{'id': 'XXX', 'created': '2025-01-16T19:55:23.411176Z', 'updated': '2025-01-16T19:57:36.450227Z', 'name': 'mybucket', 'data': {'bucket_name': 'mybucket', 'credentials': {'aws_access_key_id': '...', 'aws_secret_access_key': '********', 'region_name': 'eu-west1'}}, ...}
In the data section it shows the plain fields of the credentials. However, in other field named
"block_document_references"
I see the reference to the block mycredentials.
The problem is that in the documentation of the Prefect Cloud API (link) it is not described the schema of the data field, it is an object that depends on the specific block. And the schema of the body does not include any field named
block_document_references
. Then my question is, how can I specify the reference to mycredentials block when create the s3-bucket block? Thank you!
n
if you're using python, is there a reason you don't want to use
prefect-aws
?
Copy code
» uv run --with prefect-aws ipython
#[1]
from prefect_aws import AwsCredentials, S3Bucket

#[2]
AwsCredentials().save('test') # uses default creds a la boto3
Out[2]: UUID('053ddae0-69cc-4960-bc55-41001c75596c')

#[3]
S3Bucket(bucket_name='xyz', credentials=AwsCredentials.load('test')).save('test', overwrite=True)
Out[3]: UUID('7651bbde-52d7-474f-80b1-561688bb057f')

#[4]
S3Bucket.load('test').list_objects()
22:58:16.233 | INFO    | prefect.S3Bucket - Listing objects in bucket
Out[4]:
[{'Key': '21ee2d65bbc14f699d8823d345feea37',
  'LastModified': datetime.datetime(2024, 10, 30, 19, 37, 1, tzinfo=tzutc()),
  'ETag': '"92a28d3cfff4b8a201e3e818d34c3b2c"',
  'Size': 669,
  'StorageClass': 'STANDARD'},
 {'Key': '72b4f5acf83045399f5504d7b4806b67',
  'LastModified': datetime.datetime(2024, 10, 30, 19, 37, tzinfo=tzutc()),
  'ETag': '"92a28d3cfff4b8a201e3e818d34c3b2c"',
  'Size': 669,
  'StorageClass': 'STANDARD'}]
otherwise you can do it (with significantly more code) via REST API like this
j
Perfect, it works like charm! Thank you @Nate. Please, can you post a link to the official doc for $ref usage? It would be really helpful in my next steps
The reason why I use the API instead of python SDK is that I also want to create things like a workpool, set task concurrency limits, and other stuff that I think it is better described in the API REST doc than in the python SDK (but maybe I am wrong!)
n
better described in the API REST doc than in the python SDK
well, we have the SDK to make it easier to do these things 🙂 so hopefully it is indeed a bit easier here is the documentation on blocks, we don't have specific documentation for using blocks against the REST API because we typically would recommend the SDK or client methods to reiterate, that 100 line script against the REST api is a long way of doing the following
Copy code
» uv run --with prefect-aws ipython
#[1]
from prefect_aws import AwsCredentials, S3Bucket

#[2]
AwsCredentials().save('test') # uses default creds a la boto3
Out[2]: UUID('053ddae0-69cc-4960-bc55-41001c75596c')

#[3]
S3Bucket(bucket_name='xyz', credentials=AwsCredentials.load('test')).save('test', overwrite=True)
Out[3]: UUID('7651bbde-52d7-474f-80b1-561688bb057f')
create things like a workpool
CLI
Copy code
» prefect work-pool create local --type process
Created work pool 'local'!
client methods
Copy code
#[1]
from prefect import get_client

#[2]
from prefect.client.schemas.actions import WorkPoolCreate

#[3]
async with get_client() as client:
    print(await client.create_work_pool(WorkPoolCreate(name='testing', type='docker')))

id=UUID('bf99a0fd-864f-4420-8388-863c383cc2fd') name='testing' description=None type='docker' base_job_template={} is_paused=False concurrency_limit=None status=WorkPoolStatus.NOT_READY default_queue_id=UUID('35e00b81-cec1-4fde-914e-02c65496362d')
and similarly we have conveniences for different types of concurrency limits
j
Ok thank you for the feedback and for the links! 🙂
n
catjam