put-object and get-object commands, closes #38

pull/45/head
Simon Willison 2021-11-30 11:46:27 -08:00
rodzic 0cce643994
commit 46b6531e45
3 zmienionych plików z 86 dodań i 7 usunięć

Wyświetl plik

@ -352,6 +352,28 @@ User: s3.read-write.simonw-test-bucket-10
```
You can pass it multiple usernames to delete multiple users at a time.
### put-object
You can upload a file to a key in an S3 bucket using `s3-credentials put-object`:
s3-credentials put-object my-bucket my-key.txt /path/to/file.txt
Use `-` as the file name to upload from standard input:
echo "Hello" | s3-credentials put-object my-bucket hello.txt -
This command shows a progress bar by default. Use `-s` or `--silent` to hide the progress bar.
### get-object
To download a file from a bucket use `s3-credentials get-object`:
s3-credentials get-object my-bucket hello.txt
This defaults to outputting the downloaded file to the terminal. You can instead direct it to save to a file on disk using the `-o` or `--output` option:
s3-credentials get-object my-bucket hello.txt -o /path/to/hello.txt
## Common options
All of the `s3-credentials` commands also accept the following options for authenticating against AWS:

Wyświetl plik

@ -3,8 +3,11 @@ import boto3
import botocore
import click
import configparser
import io
import json
import os
import re
import sys
from . import policies
@ -639,3 +642,56 @@ def list_bucket(bucket, **boto_options):
for page in paginator.paginate(Bucket=bucket):
for row in page["Contents"]:
click.echo(json.dumps(row, indent=4, default=str))
@cli.command()
@click.argument("bucket")
@click.argument("key")
@click.argument(
"content",
type=click.Path(
exists=True, file_okay=True, dir_okay=False, readable=True, allow_dash=True
),
)
@click.option("silent", "-s", "--silent", is_flag=True, help="Don't show progress bar")
@common_boto3_options
def put_object(bucket, key, content, silent, **boto_options):
"Upload an object to an S3 bucket"
s3 = make_client("s3", **boto_options)
size = None
if content == "-":
# boto needs to be able to seek
fp = io.BytesIO(sys.stdin.buffer.read())
if not silent:
size = fp.getbuffer().nbytes
else:
fp = click.open_file(content, "rb")
if not silent:
size = os.path.getsize(content)
if not silent:
# Show progress bar
with click.progressbar(length=size, label="Uploading") as bar:
s3.upload_fileobj(fp, bucket, key, Callback=bar.update)
else:
s3.upload_fileobj(fp, bucket, key)
@cli.command()
@click.argument("bucket")
@click.argument("key")
@click.option(
"output",
"-o",
"--output",
type=click.Path(file_okay=True, dir_okay=False, writable=True, allow_dash=False),
help="Write to this file instead of stdout",
)
@common_boto3_options
def get_object(bucket, key, output, **boto_options):
"Download an object from an S3 bucket"
s3 = make_client("s3", **boto_options)
if not output:
fp = sys.stdout.buffer
else:
fp = click.open_file(output, "wb")
s3.download_fileobj(bucket, key, fp)

Wyświetl plik

@ -22,7 +22,7 @@ def cleanup():
cleanup_any_resources()
def test_create_bucket_with_read_write():
def test_create_bucket_with_read_write(tmpdir):
bucket_name = "s3-credentials-tests.read-write.{}".format(secrets.token_hex(4))
# Bucket should not exist
s3 = boto3.client("s3")
@ -37,17 +37,18 @@ def test_create_bucket_with_read_write():
time.sleep(10)
assert bucket_exists(s3, bucket_name)
# Use the credentials to write a file to that bucket
test_write = tmpdir / "test-write.txt"
test_write.write_text("hello", "utf-8")
get_output("put-object", bucket_name, "test-write.txt", str(test_write))
credentials_s3.put_object(
Body="hello".encode("utf-8"), Bucket=bucket_name, Key="hello.txt"
Body="hello".encode("utf-8"), Bucket=bucket_name, Key="test-write.txt"
)
# Use default s3 client to check that the write succeeded
get_object_response = s3.get_object(Bucket=bucket_name, Key="hello.txt")
get_object_response = s3.get_object(Bucket=bucket_name, Key="test-write.txt")
assert get_object_response["Body"].read() == b"hello"
# Check we can read the file using the credentials too
credentials_response = credentials_s3.get_object(
Bucket=bucket_name, Key="hello.txt"
)
assert credentials_response["Body"].read() == b"hello"
output = get_output("get-object", bucket_name, "test-write.txt")
assert output == "hello"
def test_create_bucket_read_only_duration_15():